C++中自定义事件与委托
自定义事件,和委托其实是一类操作。
在蓝图中都表现为红色方块。
自定义事件通过DECLARE_EVENT(ClassName, EventName)来创建一个属于ClassName的EventName事件。可以看出一般是没有参数的,如果蓝图中或者C++代码中自带的BeginPlay.
自定义事件
而委托则是通过DECLARE_DYNAMIC_MULTICAST_DELEGATE_'FourParams'来创建的需要根据参数个数更改FourParams。类似蓝图或者C++代码中自带的OnComponentBeginOverlap,OnComponentHit等等
委托
参考
委托和事件都相当于一个传输消息(触发点),一个接受消息(执行点)
绑定操作
这一步相当于蓝图中那些事件发生后要进行的操作,比如OnComponentHit后为了销毁粒子,那么就需要在蓝图中设置方块,连线。而在C++代码中,则需要对于有这个委托或者事件的Actor进行调用,添加设置的函数。
//对于自定义事件
Actor->EventName.AddUobject(this,&Class::Func);
//对于委托
Actor->EventName.AddDynamic(this,&Class::Func);
具体步骤
对于触发点
编写红色方块
- 声明委托或者事件(委托需要定义一个参数列表)
- 声明一个委托或者事件对象(相当于实例化一个类)--类似USphereComponent* SphereComp;
- 在需要的位置触发事件或者委托(执行或者广播),委托需要传入参数
对于执行点
一般在其他写的类中,即蓝图中红色方块之后的操作
- 利用上文绑定一些这些委托需要做的函数
- 编写函数原型
稍微综合一点就是,在一个类中实现委托或者事件的声明和调用(广播),在另一个需要操作的类中实现函数并绑定到委托或者事件中。
我们在一个ActorComponent类中声明了一个委托,并在其对应的.cpp文件中进行了广播,这个委托主要处理当生命值发生变化时的一些操作。
然后我们在Actor中绑定组件,这样在蓝图中就会显示出这个委托
接着我们在C++代码中定义了一个函数来进行角色死亡之后的操作
注意:要绑定到委托的函数的形参个数必须和委托的形参数量一致
然后利用AddDynamic绑定
重新编译后回到蓝图,就可以发现这个委托拥有了函数IsDied
而如果不适用绑定,那么就可以在蓝图中从这个委托事件连线,实现c++代码的模块连接就可以了,有点类似于将蓝图模块写好然后利用Collapse to Function使得功能变为一个Function,只不过我们直接在C++中操作了。
那么这样看来委托其实就是函数,但他相对于函数的优点就在于当发生这个事件时,会对Actor产生影响,而我们使用代理相当于时直接调用,不用传入自身self的引用。而我们使用函数,就需要确定这个函数对谁进行了操作。相当于一种解耦。
将一个普适性的东西使用委托,有利于解耦。
分类
委托分为单播,多播,动态,动态多播,事件(可以看到事件其实就是一种委托)
- 单播
在执行点绑定函数时只能绑定一个函数,比如上方示例如果绑定了IsDied就不可以绑定其他函数了,而如果绑定了多个就选择最后一个。
其一般的绑定方式为Bind*
可以拥有返回值。
在参考中有这样一个例子
DECLARE_DELEGATE_OneParam(FTestDelegate, int);
static void StaticDelegateProc(int nCode)
{
UE_LOG(LogTemp, Log, TEXT("StaticDelegateProc : %d"), nCode);
}
FTestDelegate DelegateObj1;
//绑定函数
DelegateObj1.BindStatic(StaticDelegateProc);
//通过ExcuteIfBound方法执行
DelegateObj1.ExecuteIfBound(1);
- 多播
DECLARE_MULTICAST_DELEGATE_XXXPARAMS
一般通过Add*来绑定函数,而其不会有返回值,只能通过广播来调用。
广播Broadcast()其实就是执行函数,这个委托通过Add绑定的所用函数都会被执行,我们再来看之前那个例子(虽然不是)
bool USAttributeComponent::ApplyHealthChange(float Delta)
{
if (Health <= 100.0f && Delta < 0.0f) {
Health += Delta;
OnHealthChanged.Broadcast(nullptr, this, Health, Delta);
}
if (Health < 100.0f && Delta > 0.0f) {
Health += Delta;
OnHealthChanged.Broadcast(nullptr, this, Health, Delta);
}
return true;
}
先对生命进行扣血或者加血,然后调用委托,而现在只绑定了一个函数就是IsDied,相当于就是
if (Health <= 100.0f && Delta < 0.0f) {
Health += Delta;
IsDied();
}
如果绑定了多个函数,需要注意执行顺序可能与函数的添加顺序不相同。
多播
事件
事件就是一个多播委托。
需要注意的是事件的Broadcast()只对事件所在的类有效,所以为了在想要触发事件的位置调用事件需要新建一个接口将Broadcast()放入其中。
事件动态委托和动态多播委托
主要区别就是动态委托可以在蓝图中调用,就是我们的例子,注意动态多播委托只能作为变量给蓝图调用,不能作为函数参数,而动态委托可以作为函数参数
动态单播:DECLARE_DYNAMIC_DELEGATE_XXXPARAMS
动态多播:DECLARE_DYNAMIC_MULTICAST_DELEGATE_XXXPARAM
动态委托
小结
我们使用了动态多播委托,在C++中绑定了函数给委托,并且在ApplyHealthChange函数执行时,广播了这个委托(执行函数),判断当前角色血量这个操作。
那么在蓝图中如何绑定一个函数(事件)给这个动态多播委托呢?
参考
可以看到OnMyDelegate2为我们的动态多播委托,而charDelegate为我们要绑定的事件,类似我们写的IsDied函数。
之后继续在委托编写的类中定义了一个触发委托广播的函数TestBpDelegate,在蓝图中使用按键来执行。
C++中自定义事件与委托的更多相关文章
- 1 .net中自定义事件的步骤
1 申明一个自定义的类并且继承事件的基类 public class ClientSocketModelConnectedEvent:EventArgs { private string param; ...
- 《C#高级编程》学习笔记------C#中的事件和委托
本文转载自张子阳 目录 委托的作用 将方法绑定到委托 事件的来由 Observer设计模式 .Net Framework中的委托与事件 引言 委托 和 事件在 .Net Framework中的应用 ...
- Extjs中自定义事件
//Ext中所谓的响应事件,响应的主要是组件中已经定义的事件(通过看api各组件的events可以找到) //主要作用就是利用on调用各组件的事件处理函数,然后在函数中作用户想要的操作 ...
- javascript中自定义事件
自定义事件:用户可以指定事件类型,这个类型实际上就是一个字符串,然后为这个类型的事件指定事件处理函数,可以注册多个事件处理函数(用数组管理),调用时,从多个事件处理函数中找到再调用. function ...
- 使用jQuery在javascript中自定义事件
js中的自定义事件有attachEvent,addEventListener等等好多种,往往受困于浏览器兼容,而且代码写起来也相当麻烦.jQuery为我们解决了这个问题,几行代码就可以很好的实现事件的 ...
- php中自定义事件---事件驱动
PHP中自定义事件驱动,处理机制. 原文:https://www.cnblogs.com/mafeifan/p/4322271.html ------------------------------- ...
- Vue中调用另一个组件中自定义事件
之前在一个场景中,遇到组件需要调用父组件中的方法tableInit(),字组件调用父组件常用的有三种方法,具体参考:https://www.cnblogs.com/jin-zhe/p/9523782. ...
- js中自定义事件,使用了jQuery
$(function(){ $('#btn').bind("myClick", function(){ //自定义myClick事件 $('#test').append(" ...
- JS中自定义事件的使用与触发
1. 事件的创建 JS中,最简单的创建事件方法,是使用Event构造器: var myEvent = new Event('event_name'); 但是为了能够传递数据,就需要使用 CustomE ...
- JavaScript中的事件代理/委托
事件委托在JS高级程序设计中的定义为"利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件" 如何理解上面的这句话呢,在网上,大牛们一般都使用收快递这个例子来解释的, ...
随机推荐
- Java I/O 教程(八) Writer和Reader
Java Writer Writer是一个用于写字符流的抽象类.其子类必须实现write(char[], int, int), flush(), 和 close()方法. 类定义 public abs ...
- python课本学习-第五章
一.列表的概念 1.列表的创建 列表是由一组任意类型的值组合而成的序列,组成列表的值称为元素,每个元素之间用逗号隔开. 列表中的元素是可变的 #列表类似于c++中的数组,数组下标从0开始 list1 ...
- kubernetes(k8s)大白学习01-kubernetes是什么?有什么用?
kubernetes(k8s)大白基础学习-kubernetes是什么? 一.认识 Docker Docker 是什么 先来看看 Docker 的图标: 一条鲸鱼背上驮着四方形块的物品,就像一条海运船 ...
- 了解企业架构EA(Enterprise Architecture)
一.企业架构简介 企业架构:Enterprise Architecture,EA,或企业体系结构,是在信息系统架构设计与实践基础上发展起来的一个特殊领域. 但是企业架构现在还没有一个公认的定义,综合现 ...
- AI与人类联手,智能排序人类决策:RLHF标注工具打造协同标注新纪元,重塑AI训练体验
AI与人类联手,智能排序人类决策:RLHF标注工具打造协同标注新纪元,重塑AI训练体验 在大模型训练的 RLHF 阶段,需要人工对模型生成的多份数据进行标注排序,然而目前缺乏开源可用的 RLHF 标注 ...
- STL-RBTree模拟实现
#pragma once #include<assert.h> #include<iostream> using std::cout; using std::endl; usi ...
- Java 临时笔记
1 //srand((unsignedint)time(NULL)); C 2 //获取随机数 10-99 3 4 //int value = (int)(Math.random() * 90+10) ...
- MongoDB可视化compass 连接数据库失败Invalid UTF-8 string in BSON document
An error occurred while loading navigation: Invalid UTF-8 string in BSON document 出现这个问题建议降低compass版 ...
- MYSQL索引-下
前言 丁奇老师的 MYSQL45讲 的关于索引的的两节 深入浅出索引,做个笔记 覆盖索引 插入一个实例表 mysql> create table T ( ID int primary key, ...
- .bat 批处理 手册 教程
有时候bat写个脚本 还是挺方便的,网上也没有不错的手册,有时间再整理看吧.网上找几个,先留存. 系统变量 %USERPROFILE% https://blog.csdn.net/ztx114/art ...