自定义事件,和委托其实是一类操作。

在蓝图中都表现为红色方块。

自定义事件通过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);

具体步骤

对于触发点

编写红色方块

  1. 声明委托或者事件(委托需要定义一个参数列表)
  2. 声明一个委托或者事件对象(相当于实例化一个类)--类似USphereComponent* SphereComp;
  3. 在需要的位置触发事件或者委托(执行或者广播),委托需要传入参数

对于执行点

一般在其他写的类中,即蓝图中红色方块之后的操作

  1. 利用上文绑定一些这些委托需要做的函数
  2. 编写函数原型

稍微综合一点就是,在一个类中实现委托或者事件的声明和调用(广播),在另一个需要操作的类中实现函数并绑定到委托或者事件中。

我们在一个ActorComponent类中声明了一个委托,并在其对应的.cpp文件中进行了广播,这个委托主要处理当生命值发生变化时的一些操作。





然后我们在Actor中绑定组件,这样在蓝图中就会显示出这个委托



接着我们在C++代码中定义了一个函数来进行角色死亡之后的操作



注意:要绑定到委托的函数的形参个数必须和委托的形参数量一致

然后利用AddDynamic绑定



重新编译后回到蓝图,就可以发现这个委托拥有了函数IsDied



而如果不适用绑定,那么就可以在蓝图中从这个委托事件连线,实现c++代码的模块连接就可以了,有点类似于将蓝图模块写好然后利用Collapse to Function使得功能变为一个Function,只不过我们直接在C++中操作了。

那么这样看来委托其实就是函数,但他相对于函数的优点就在于当发生这个事件时,会对Actor产生影响,而我们使用代理相当于时直接调用,不用传入自身self的引用。而我们使用函数,就需要确定这个函数对谁进行了操作。相当于一种解耦。

将一个普适性的东西使用委托,有利于解耦。

分类

委托分为单播,多播,动态,动态多播,事件(可以看到事件其实就是一种委托)

  1. 单播

    在执行点绑定函数时只能绑定一个函数,比如上方示例如果绑定了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);
  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();
}

如果绑定了多个函数,需要注意执行顺序可能与函数的添加顺序不相同。

多播

  1. 事件

    事件就是一个多播委托。



    需要注意的是事件的Broadcast()只对事件所在的类有效,所以为了在想要触发事件的位置调用事件需要新建一个接口将Broadcast()放入其中。

    事件

  2. 动态委托和动态多播委托

    主要区别就是动态委托可以在蓝图中调用,就是我们的例子,注意动态多播委托只能作为变量给蓝图调用,不能作为函数参数,而动态委托可以作为函数参数

    动态单播:DECLARE_DYNAMIC_DELEGATE_XXXPARAMS

    动态多播:DECLARE_DYNAMIC_MULTICAST_DELEGATE_XXXPARAM

    动态委托

小结

我们使用了动态多播委托,在C++中绑定了函数给委托,并且在ApplyHealthChange函数执行时,广播了这个委托(执行函数),判断当前角色血量这个操作。

那么在蓝图中如何绑定一个函数(事件)给这个动态多播委托呢?

参考



可以看到OnMyDelegate2为我们的动态多播委托,而charDelegate为我们要绑定的事件,类似我们写的IsDied函数。

之后继续在委托编写的类中定义了一个触发委托广播的函数TestBpDelegate,在蓝图中使用按键来执行。

C++中自定义事件与委托的更多相关文章

  1. 1 .net中自定义事件的步骤

    1 申明一个自定义的类并且继承事件的基类 public class ClientSocketModelConnectedEvent:EventArgs { private string param; ...

  2. 《C#高级编程》学习笔记------C#中的事件和委托

    本文转载自张子阳 目录 委托的作用 将方法绑定到委托 事件的来由 Observer设计模式 .Net Framework中的委托与事件   引言 委托 和 事件在 .Net Framework中的应用 ...

  3. Extjs中自定义事件

    //Ext中所谓的响应事件,响应的主要是组件中已经定义的事件(通过看api各组件的events可以找到)         //主要作用就是利用on调用各组件的事件处理函数,然后在函数中作用户想要的操作 ...

  4. javascript中自定义事件

    自定义事件:用户可以指定事件类型,这个类型实际上就是一个字符串,然后为这个类型的事件指定事件处理函数,可以注册多个事件处理函数(用数组管理),调用时,从多个事件处理函数中找到再调用. function ...

  5. 使用jQuery在javascript中自定义事件

    js中的自定义事件有attachEvent,addEventListener等等好多种,往往受困于浏览器兼容,而且代码写起来也相当麻烦.jQuery为我们解决了这个问题,几行代码就可以很好的实现事件的 ...

  6. php中自定义事件---事件驱动

    PHP中自定义事件驱动,处理机制. 原文:https://www.cnblogs.com/mafeifan/p/4322271.html ------------------------------- ...

  7. Vue中调用另一个组件中自定义事件

    之前在一个场景中,遇到组件需要调用父组件中的方法tableInit(),字组件调用父组件常用的有三种方法,具体参考:https://www.cnblogs.com/jin-zhe/p/9523782. ...

  8. js中自定义事件,使用了jQuery

    $(function(){ $('#btn').bind("myClick", function(){ //自定义myClick事件 $('#test').append(" ...

  9. JS中自定义事件的使用与触发

    1. 事件的创建 JS中,最简单的创建事件方法,是使用Event构造器: var myEvent = new Event('event_name'); 但是为了能够传递数据,就需要使用 CustomE ...

  10. JavaScript中的事件代理/委托

    事件委托在JS高级程序设计中的定义为"利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件" 如何理解上面的这句话呢,在网上,大牛们一般都使用收快递这个例子来解释的, ...

随机推荐

  1. Java Solon v2.7.0 发布

    Java Solon 是什么框架? Java "生态级"应用开发框架.从零开始构建,有自己的标准规范与开放生态.(历时七年,具备全球第二级别的生态规模) 相对于 Spring,有什 ...

  2. 阿里OSS+PicGo+Typora图床设置使用

    1.首先下载Typroa和PicGo Typroa地址: 链接:https://pan.baidu.com/s/1M6_5o1PZyaGqOhSb4yvtmA 提取码:a1aj PicGo地址: 链接 ...

  3. 栈溢出-ret2libc地址泄露笔记

    作为一名初学者,在碰到很多攻击思路的时候会感觉很妙,比如gadget的构造,这题的sh参数截断. 1.首先分析程序架构和保护措施. 2.使用IDA开始判断程序是否具备最简单的栈溢出执行条件: ret2 ...

  4. C++ 值,指针,引用的讨论

    源自 stackoverflow 论坛,很有意义 第一个问题,引用传递和按值传递的场合 There are four main cases where you should use pass-by-r ...

  5. 配置kube-apiserver基于token的认证机制

    Kubernetes除了提供了基于CA证书的认证方式,也提供了基于HTTP Token的简单认证方式.各客户端组件与API Server之间的通信方式仍然采用HTTPS,但不采用CA数字证书.这种认证 ...

  6. 如何处理Long类型精度丢失问题?

    一.现象与分析: 1.1. 现象 前后端交互,当后端传一些值给前端的时候,如果是long类型,有可能会出现数字太大而前端接收不了(java中的long大于js的number)而导致数据不一致,精度会丢 ...

  7. ABP开发需要用到的命令

    0.命令行在哪里执行? 在Visual Studio的"解决方案资源管理器"的解决方案或者项目上点鼠标右键,选择"在终端中打开". 1.安装abp的命令行 官网 ...

  8. 一: Mysql字符集问题

    ## Mysql 字符集问题 1 修改MySQL5.7字符集 1.1 修改步骤 在MySQL 8.0版本之前,默认字符集为 latin1 ,utf8字符集指向的是 utf8mb3 .网站开发人员在数据 ...

  9. apt-get upgrade 和apt-get dist-upgrade区别

    kali  linux系统或者 debian等系统 以及centos  在系统升级后经常会出现系统无法启动,或者启动之后GUI功能没有的问题: 笔记:   区别这两种用法 apt-get update ...

  10. CPN Tools 系统建模分析工具(持续更新)

    一直想把之前看有关CPN的文献资料做一个综合性的整理,所以最近花了些时间,把乌克兰敖德萨国家电信科学院交通运输部学院的讲义做一个翻译.本课程的翻译不具授权(如有侵权请及时联系,做删除处理) 本课程的标 ...