学习虚幻C++开发日志——委托(持续更新中)
委托
官方文档:Delegates and Lamba Functions in Unreal Engine | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community
简单地说,委托就像是一个“函数指针”,但它更加安全和灵活。它允许程序在运行时动态地调用不同的函数。
(1)解耦对象间的关联
委托允许对象之间以松散耦合的方式进行通信。通过委托,一个对象可以在不直接引用另一个对象的情况下,通知其执行特定的操作。这有助于降低对象之间的依赖性和耦合度,从而提高代码的灵活性和可维护性。
(2)事件驱动编程
委托是实现事件驱动编程的关键机制之一。在事件驱动编程中,对象的行为是基于事件的发生来触发的。委托允许对象在事件发生时通知其他对象,并允许这些对象对事件做出响应。这种机制使得代码更加模块化,并易于扩展和维护。
(3)泛型且类型安全
委托提供了一种泛型但类型安全的方式,在C++对象上调用成员函数。通过委托,你可以动态地绑定到任意对象的成员函数,即使调用程序不知道对象的具体类型也可以进行操作。这增加了代码的灵活性和可重用性,同时保证了类型安全。
(4)异步通信
委托还支持异步通信。在虚幻引擎中,许多操作可能需要花费一些时间才能完成,如加载资源、执行物理模拟等。通过使用委托,你可以在不阻塞主线程的情况下,通知其他对象在异步操作完成后执行特定的操作。这有助于提高应用程序的响应性和性能。
(5)广播和多播
虚幻引擎中的委托还支持广播和多播机制。广播允许一个委托通知所有绑定的对象,而多播则允许一个委托通知多个指定的对象。这种机制使得在多个对象之间传递消息变得更加简单和高效。
(6)蓝图可视化编程支持
在虚幻引擎的蓝图可视化编程环境中,委托也扮演着重要的角色。通过委托,蓝图脚本可以轻松地与C++代码进行交互,从而实现更加复杂和灵活的游戏逻辑。此外,蓝图还支持动态多播委托的声明和使用,这使得在蓝图中处理事件和消息变得更加方便。
(7)复制和安全性
委托对象在复制时是很安全的。你可以通过值或引用来传递委托,但需要注意的是,通过值传递需要在堆上分配内存,这通常不是最佳实践。通过引用传递则更加高效且安全。
但传递引用,在异步的情况下会涉及到生命周期问题,容易崩溃,虚幻的委托大部分时候拷贝是安全的,因为它会存一个执行委托对象的弱引用,如果这对象消亡了,那么这个委托被调用的时候就不会执行。
委托的大致使用流程
- 声明委托类型
- 定义委托类型变量
- 通过委托变量绑定委托函数
- 执行委托
- 解绑委托函数(可根据自身情况而实施)
1.单播
先创建一个继承于Actor的类,并在其头文件包含头文件(此处文件命名为LearnSingleDelegateActor)
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LearnSingleDelegateActor.generated.h"
并在源文件添加GameplayStatics.h头文件
#include"Kismet/GameplayStatics.h"
(1)声明委托类型
DECLARE_DELEGATE(FLearnSingleDelegatePrintLocation);
DECLARE_DELEGATE_RetVal_OneParam(FVector,FLearnSingleDelegateGetLocation,FString);
//DECLARE_DELEGATE_RetVal_OneParam(ReturnType, DelegateName, ParamType);
//ReturnType:委托将要返回的值的类型。
//DelegateName:委托的名称,这个名称将用于在代码中引用这个委托类型。
//ParamType:委托将要接受的参数的类型。
如需声明委托,请使用下文所述的宏。请根据与委托相绑定的函数(或多个函数)的函数签名来选择宏。每个宏都为新的委托类型名称、函数返回类型(如果不是 void 函数)及其参数提供了参数。当前,支持以下使用任意组合的委托签名:
- 返回一个值的函数。
- 声明为常函数。
- 最多4个"载荷"变量。
- 最多8个函数参数。

注意:委托函数支持与UFunctions相同的说明符,但使用 UDELEGATE 宏而不是 UFUNCTION。
(2)定义委托类型变量
在ALearnSingleDelegateActor类内定义变量
public:FLearnSingleDelegatePrintLocation SingleDelegatePrintLocation;FLearnSingleDelegateGetLocation SingleDelegateGetLocation;
(3)通过委托变量绑定委托函数
为方便在ALearnSingleDelegateActor类头文件再创建一个类,此处命名为LearnLocationActor(继承于Actor)
UCLASS()
class ALearnLocationActor : public AActor
{GENERATED_BODY()public:ALearnLocationActor();protected:virtual void BeginPlay() override;void PrintLocation();FVector GetLocation(FString InStr);//此处类型看委托声明处,与其相对应.
};
在此默认函数中创建根组件来便于观察委托操作 ,并对其他函数进行定义
ALearnLocationActor::ALearnLocationActor()
{RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("LocationRoot"));
}void ALearnLocationActor::PrintLocation()
{FVector MyLocation = GetActorLocation();UE_LOG(LogTemp, Warning, TEXT("[%s]__PrintMyLocation:[%s]"), *FString(__FUNCTION__), *MyLocation.ToString());//用于被绑定时观察步骤实现
}FVector ALearnLocationActor::GetLocation(FString InStr)
{FVector MyLocation = GetActorLocation();UE_LOG(LogTemp, Warning, TEXT("[%s]__GetMyLocation:[%s]"), *FString(__FUNCTION__), *MyLocation.ToString());return MyLocation;
}
此处绑定函数
void ALearnLocationActor::BeginPlay()
{AActor *ActorPtr = UGameplayStatics::GetActorOfClass(this, ALearnSingleDelegateActor::StaticClass());if (ALearnSingleDelegateActor* SingleDelegateActorPtr=Cast<ALearnSingleDelegateActor>(ActorPtr)){//通过SingleDelegatePrintLocation此委托变量使用BindUObject函数模板绑定委托并调用一次绑定函数SingleDelegateActorPtr->SingleDelegatePrintLocation.BindUObject(this,&ALearnLocationActor::PrintLocation);SingleDelegateActorPtr->SingleDelegateGetLocation.BindUObject(this, &ALearnLocationActor::GetLocation);}
}
官方模板函数
(4) 执行委托
为了观察实现步骤,我在LearnSingleDelegateActor类声明函数暴露给蓝图
UFUNCTION(BlueprintCallable, Category = "Learn")void CallLocationActorPrint();UFUNCTION(BlueprintCallable, Category = "Learn")void CallLocationActorGet();
并对其进行定义
void ALearnSingleDelegateActor::CallLocationActorPrint()
{//第一种写法if (SingleDelegatePrintLocation.IsBound()){SingleDelegatePrintLocation.Execute();//SingleDelegatePrintLocation.Unbind();解绑操作}//第二种写法(建议用此写法)SingleDelegatePrintLocation.ExecuteIfBound();
}void ALearnSingleDelegateActor::CallLocationActorGet()
{FVector MyRecetivedLocation = SingleDelegateGetLocation.Execute(TEXT("My Single Delegate Actor"));UE_LOG(LogTemp, Warning, TEXT("[MyRecetivedLocation]__MyLocation:[%s]"), *MyRecetivedLocation.ToString());
}

注意:对于无返回值的委托,可调用ExecuteIfBound()函数,但需注意输出参数可能未初始化。
(5)观察实现步骤(只做演示)
1、将两个类拖入场景中

2、在关卡蓝图处使用函数(此处是使用键盘1、2分别去激活函数)

3、启动关卡,并在输出日志观察


2.多播
3.动态单播
4.动态多播
相关文章:
学习虚幻C++开发日志——委托(持续更新中)
委托 官方文档:Delegates and Lamba Functions in Unreal Engine | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 简单地说,委托就像是一个“函数指针”,但它更加安全和灵活。它允许程序在运行时动态地调用不…...
开窗函数 - first_value/last_value
1、开窗函数是什么? 开窗函数用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用 GROUP BY 子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。 2、…...
「一」HarmonyOS端云一体化概要
关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 「目录」 「一」HarmonyOS端云一体化概要 「二」体验HarmonyOS端云一…...
nodejs21: 快速构建自定义设计样式Tailwind CSS
Tailwind CSS 是一个功能强大的低级 CSS 框架,只需书写 HTML 代码,无需书写 CSS,即可快速构建美观的网站。 1. 安装 Tailwind CSS React 项目中安装 Tailwind CSS: 1.1 安装 Tailwind CSS 和相关依赖 安装 Tailwind CSS: npm…...
从JSON数据提取嵌套字段并转换为独立列的简洁方法
从JSON数据提取嵌套字段并转换为独立列的简洁方法 在数据处理和数据分析的日常工作中,我们经常遇到复杂的嵌套数据结构,特别是嵌入在JSON字段中的数据。这些数据往往需要解析并展开成独立的列,以便后续分析和建模。本文将详细介绍如何在Pyth…...
湘潭大学软件工程算法设计与分析考试复习笔记(四)
回顾 湘潭大学软件工程算法设计与分析考试复习笔记(一)湘潭大学软件工程算法设计与分析考试复习笔记(二)湘潭大学软件工程算法设计与分析考试复习笔记(三) 前言 现在是晚上十一点,我平时是十…...
特征交叉-DeepCross Network学习
一 tensorflow官方实现 tensorflow的官方实现已经是V2版本 class Cross(tf.keras.layers.Layer):"""Cross Layer in Deep & Cross Network to learn explicit feature interactions.Args:projection_dim: int,低秩矩阵的维度,应该小…...
stm32cubemx+VSCODE+GCC+makefile 开发环境搭建
title: stm32cubemxVSCODEGCCmakefile 开发环境搭建 tags: FreertosHalstm32cubeMx 文章目录 内容往期内容导航第一步准备环境vscode 插件插件配置点灯 内容 往期内容导航 第一步准备环境 STM32CubeMXVSCODEMinGWOpenOcdarm-none-eabi-gcc 然后把上面下载的软件 3 4 5 bin 文…...
Go语言中的Defer机制详解与示例
在Go语言中,defer是一个关键字,用于确保资源的清理和释放,特别是在函数中创建的资源。defer语句会将其后的函数调用推迟到包含它的函数即将返回时执行。这使得defer成为处理文件关闭、数据库连接释放、解锁等资源清理操作的理想选择。 Defer…...
H.265流媒体播放器EasyPlayer.js H5流媒体播放器如何验证视频播放是否走硬解
随着技术的不断进步和5G网络的推广,中国流媒体播放器行业市场规模以及未来发展趋势都将持续保持稳定的增长,并将在未来几年迎来新的发展机遇。流媒体播放器将继续作为连接内容创作者和观众的重要桥梁,推动数字媒体产业的创新和发展。 EasyPla…...
ms-hot目录
1. ms-hot1...
vulfocus在线靶场:骑士cms_cve_2020_35339:latest 速通手册
目录 一、启动环境,访问页面,ip:端口号/index.php?madmin,进入后台管理页面,账号密码都是adminadmin 二、进入之后,根据图片所示,地址后追加一下代码,保存修改 三、新开标签页访问:①ip:端…...
AI Large Language Model
AI 的 Large Language model LLM , 大语言模型: 是AI的模型,专门设计用来处理自然语言相关任务。它们通过深度学习和庞大的训练数据集,在理解和生成自然语言文本方面表现出色。常见的 LLM 包括 OpenAI 的 GPT 系列、Google 的 PaLM 和 Meta…...
React Native的`react-native-reanimated`库中的`useAnimatedStyle`钩子来创建一个动画样式
React Native的react-native-reanimated库中的useAnimatedStyle钩子来创建一个动画样式,用于一个滑动视图的每个项目(SliderItem)。useAnimatedStyle钩子允许你根据动画值(在这个例子中是scrollX)来动态地设置组件的样…...
FastJson反序列化漏洞(CVE-2017-18349)
漏洞原理 原理就不多说了,可以去看我这篇文章,已经写得很详细了。 Java安全—log4j日志&FastJson序列化&JNDI注入-CSDN博客 影响版本 FastJson<1.2.24 复现过程 这里我是用vulfocus.cn这个漏洞平台去复现的,比较方便&#x…...
【优选算法篇】分治乾坤,万物归一:在重组中窥见无声的秩序
文章目录 分治专题(二):归并排序的核心思想与进阶应用前言、第二章:归并排序的应用与延展2.1 归并排序(medium)解法(归并排序)C 代码实现易错点提示时间复杂度和空间复杂度 2.2 数组…...
C++:探索AVL树旋转的奥秘
文章目录 前言 AVL树为什么要旋转?一、插入一个值的大概过程1. 插入一个值的大致过程2. 平衡因子更新原则3. 旋转处理的目的 二、左单旋1. 左单旋旋转方式总处理图2. 左单旋具体会遇到的情况3. 左单旋代码总结 三、右单旋1. 右单旋旋转方式总处理图2. 右单旋具体会遇…...
2. Django中的URL调度器 (自定义路径转换器)
在 Django 中,URL 路由通常使用路径转换器(path converters)来匹配和捕获 URL 中的特定模式,例如整数、字符串或 slug 等。默认情况下,Django 提供了一些内置的路径转换器,如 <int>、<str>、&l…...
深度学习:神经网络中线性层的使用
深度学习:神经网络中线性层的使用 在神经网络中,线性层(也称为全连接层或密集层)是基础组件之一,用于执行输入数据的线性变换。通过这种变换,线性层可以重新组合输入数据的特征,并将其映射到新…...
【刷题】算法设计题+程序设计题【2】2019-2024
11.202019年真题*2BST二叉排序树分裂、双向冒泡排序 2019 真题 【2019 1】编写算法,将一棵二叉排序树 分解成两棵二叉排序树 t1和t2,使得t1中的所有结点关键字的值都小于x,t2中所有结点关键字都大于x。 typedef struct BSTNode{int data;str…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
