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高级程序设计中的定义为"利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件" 如何理解上面的这句话呢,在网上,大牛们一般都使用收快递这个例子来解释的, ...
随机推荐
- 栈溢出-ret2libc地址泄露笔记
作为一名初学者,在碰到很多攻击思路的时候会感觉很妙,比如gadget的构造,这题的sh参数截断. 1.首先分析程序架构和保护措施. 2.使用IDA开始判断程序是否具备最简单的栈溢出执行条件: ret2 ...
- 我的小程序之旅八:基于weixin-java-mp实现微信公众号被动回复消息
在微信里有这样一个公众号[华为运动健康],当点击最新排行的时候,公众号就会发送今天最新的运动步数给你.如下图: 这里有两种格式的消息 1.有头像框,有聊天框--普通消息 2.消息有样式.颜色等--模板 ...
- [Android逆向] 重打包时报BrutException
执行apktool b --use-aapt2 进行重打包时,重打包失败,抛出异常 apktool b /Users/***/work/appsApk/testApp --use-aapt2 I: U ...
- 学习go语言编程之流程控制
Golang支持如下4种流程控制语句: 条件语句:if,else和else if 选择语句:switch,case和select 循环语句:for,range 跳转语句:goto 条件语句 示例代码: ...
- Thinkpad T14 AMD版无线网卡不可用
硬件环境: Thinkpad T14 AMD 操作系统: Windows 10家庭版 问题描述: Windows 10在后台默默做了补丁更新,导致无线网卡和蓝牙鼠标都不可用(但是有线网却是能正常工作的 ...
- 项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端
需求 1.Qt已经开发了应用,封装成Qt库,以供C#调用. 2.Qt的tcp客户端封装,以供C#调用,双向传递数据. 原理 1.使用QtCreator编译msvc版本的Qt库: 2.使 ...
- 无所不谈,百无禁忌,Win11本地部署无内容审查中文大语言模型CausalLM-14B
目前流行的开源大语言模型大抵都会有内容审查机制,这并非是新鲜事,因为之前chat-gpt就曾经被"玩"坏过,如果没有内容审查,恶意用户可能通过精心设计的输入(prompt)来操纵L ...
- 【Azure Redis】PHPRedis遇见SSL Connection Timeout问题
问题描述 PHP Redis客户端遇见使用SSL Connection timeout,遇见问题后,切换回去Non-SSL没有出现问题.但是切换回SSL后,还是偶尔遇见Connection timeo ...
- XSS漏洞原理整理
一.通常使用XSS脚本来获取浏览器版本信息,alert(navigator.userAgnet ) ,浏览器的UserAgent是可以伪造的,比方火狐或者很多扩展都可以屏蔽或者自定义浏览器发送的Us ...
- guava和redis 都是缓存用的,不过redis要起服务,guava不用起服务
guava和redis 都是缓存用的,不过redis要起服务,guava不用起服务