[UE4]事件处理(Handling Events)和委托(Delegate)代码示例(二)【C++】
3. 创建带参数的委托
我们可以通过修改委托的签名来使其接受参数
比如我们需要接受一个参数的话,可以在 GameMode 中这样声明:
DECLARE_DELEGATE_OneParam(FParamDelegateSignature, FLinearColor)
注意:这个宏与之前稍有不同,后缀多出了一个 _OneParam ,而且我们还需要指定接受参数的类型——本例为 FLinearColor
接着再添加一个 FParamDelegateSignature 成员
FParamDelegateSignature MyParameterDelegate;
这和之前一样,创建一个委托实例作为 GameMode 成员
然后创建一个 Actor 类,取名为 ParamDelegateListener,
在头文件中添加以下声明
UFUNCTION()
void SetLightColor(FLinearColor LightColor); UPROPERTY()
UPointLightComponent* PointLight;
ParamDelegateListener.cpp
#include "Test.h"
#include "UE4TestGameMode.h"
#include "ParamDelegateListener.h" // Sets default values
AParamDelegateListener::AParamDelegateListener()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
PointLight = CreateDefaultSubobject<UPointLightComponent>("PointLight");
RootComponent = PointLight; } // Called when the game starts or when spawned
void AParamDelegateListener::BeginPlay()
{
Super::BeginPlay();
UWorld* TheWorld = GetWorld();
if (TheWorld != nullptr)
{
AGameMode* GameMode = Cast<AGameMode>(UGameplayStatics::GetGameMode(TheWorld));
AUE4TestGameMode * MyGameMode = Cast<AUE4TestGameMode>(GameMode);
if (MyGameMode != nullptr)
{
// Binds a UObject-based member function delegate. UObject delegates keep a weak reference to your object. You can use ExecuteIfBound() to call them.(注意绑定的还是 UFUNCTION)
MyGameMode->MyParameterDelegate.BindUObject(this, &AParamDelegateListener::SetLightColor);
}
} } // Called every frame
void AParamDelegateListener::Tick( float DeltaTime )
{
Super::Tick( DeltaTime ); }
// 1个参数
void AParamDelegateListener::SetLightColor(FLinearColor LightColor)
{
PointLight->SetLightColor(LightColor);
}
回到 MyTriggerVollume.cpp,在 NotifyActorBeginOverlap 函数中添加以下代码:
MyGameMode->MyParameterDelegate.ExecuteIfBound(FLinearColor(, , , )); // 带一个参数
与之前不同的是,我们需要多指定一个参数,参数类型和我们之前的委托声明一致。
显然,MyTriggerVolume 压根就无需知道 ParamDelegateListener 的存在,却通过 GameMode 就可以调用 ParamDelegateListener 的函数了,很大程度上降低了类间的耦合度。
解绑委托方式与之前相同,不再赘述。
4.通过委托绑定传递负载数据(Payload Data)
稍加修改,我们就可以在委托被调用时传递额外创建时的参数(additional creation-time parameter),即我们在 MyTriggerVolume 中的调用方式不变,仍然是 ExecuteIfBound(FLinearColor(1, 0, 0, 1)),但可以额外添加一些负载数据,在 ParamDelegateListener 中的 BindUObject 上添加。
首先修改 AParamDelegateListener::BeginPlay 中的 BindUObject,为其添加一个 bool 负载数据
MyGameMode->MyParameterDelegate.BindUObject(this, &AParamDelegateListener::SetLightColor, false);
并修改 SetLightColor 的定义
UFUNCTION()
void SetLightColor(FLinearColor LightColor, bool EnableLight);
// 2个参数
void AParamDelegateListener::SetLightColor(FLinearColor LightColor, bool EnableLight)
{
PointLight->SetLightColor(LightColor);
PointLight->SetVisibility(EnableLight);
}
注意:负载数据并不局限于带参数的委托,其他的委托形式也可以使用
5. 多播委托(Multicast Delegate)
之前说的委托,都是只绑定了一个函数指针,而多播委托绑定的是一个函数指针集合,每个函数指针都有对应的一个委托句柄,当广播(Broadcast)委托的时候,他们将会被激活。
首先在 GameMode 中添加多播的委托声明
需要明确声明为多播
DECLARE_MULTICAST_DELEGATE(FMulticastDelegateSignature)
接着在类中声明一个 FMulticastDelegateSignature 成员
FMulticastDelegateSignature MyMulticastDelegate;
其次,创建一个新 Actor 类,命名为 MulticastDelegateListener
在其头文件中添加以下声明:
FDelegateHandle MyDelegateHandle; UPROPERTY()
UPointLightComponent* PointLight; UFUNCTION()
void ToggleLight(); virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
大部分和之前的 Listener 类很相似,但是多一个 委托句柄实例,将用它来存储委托实例的引用,我们的添加(AddUObject)和移除(Remove)都需要它作为参数
源文件的代码如下:
// Sets default values
AMulticastDelegateListener::AMulticastDelegateListener()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
PointLight = CreateDefaultSubobject<UPointLightComponent>("PointLight");
RootComponent = PointLight; } // Called when the game starts or when spawned
void AMulticastDelegateListener::BeginPlay()
{
Super::BeginPlay();
UWorld* TheWorld = GetWorld();
if (TheWorld != nullptr)
{
AGameMode* GameMode = Cast<AGameMode>(UGameplayStatics::GetGameMode(TheWorld));
AUE4TestGameMode * MyGameMode = Cast<AUE4TestGameMode>(GameMode);
if (MyGameMode != nullptr)
{
// Adds a UObject-based member function delegate. UObject delegates keep a weak reference to your object.
// 注册一个对象方法
MyDelegateHandle = MyGameMode->MyMulticastDelegate.AddUObject(this, &AMulticastDelegateListener::ToggleLight);
}
} } // Called every frame
void AMulticastDelegateListener::Tick( float DeltaTime )
{
Super::Tick( DeltaTime ); } void AMulticastDelegateListener::ToggleLight()
{
PointLight->ToggleVisibility();
} void AMulticastDelegateListener::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
UWorld* TheWorld = GetWorld();
if (TheWorld != nullptr)
{
AGameMode* GameMode = Cast<AGameMode>(UGameplayStatics::GetGameMode(TheWorld));
AUE4TestGameMode * MyGameMode = Cast<AUE4TestGameMode>(GameMode);
if (MyGameMode != nullptr)
{
// Removes a function from this multi-cast delegate's invocation list (performance is O(N)). Note that the order of the delegates may not be preserved!
MyGameMode->MyMulticastDelegate.Remove(MyDelegateHandle);
}
}
}
MyTriggerVolume.cpp 的实现为:
// Broadcasts this delegate to all bound objects, except to those that may have expired.
MyGameMode->MyMulticastDelegate.Broadcast();
广播函数很像我们之前的 ExecuteIfBound函数,但有一点不同,它不需要检查是否有函数绑定在委托上。
最后的效果是,如果我们往场景中拖放了四五个MulticastDelegateListener,当我们进入触发区域,它们的灯会同时打开或关闭,因为每个实例函数都被添加到委托集合当中;
如果拖放了四五个DelegateListener 到场景中,当我们进入触发区域,只有最后一个拖进场景的灯会亮,这是因为委托只绑定了最后一个实例函数。
[UE4]事件处理(Handling Events)和委托(Delegate)代码示例(二)【C++】的更多相关文章
- [UE4]事件处理(Handling Events)和委托(Delegate)代码示例(一)
1. 通过重写虚函数来处理事件 MyTriggerVolume.h 自定义一个Actor类,添加一个 Box 组件作为触发区域,然后通过重写虚函数——NotifyActorBeginOverlap, ...
- 【UE4 C++ 基础知识】<8> Delegate 委托
概念 定义 UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系. 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到 ...
- 关于C# 委托(delegate)与事件(event)的用法及事例
C#中的委托和事件对于新手可能会有一点难理解,所以先从一个小例子入手,以便能更好的理解其如何使用.有一个学生每天定闹钟在早上6点起床,所以当每天早上6点的时候,闹钟就会响起来,从而学生才会按时起床. ...
- C# 委托Delegate(一) 基础介绍&用法
本文是根据书本&网络 前人总结的. 1. 前言 定义&介绍: 委托Delegate是一个类,定义了方法的类型, 使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的 ...
- C#基础知识六之委托(delegate、Action、Func、predicate)
1. 什么是委托 官方解释 委托是定义方法签名的类型,当实例化委托时,您可以将其实例化与任何具有兼容签名的方法想关联,可以通过委托实例调用方法. 个人理解 委托通俗一点说就是把一件事情交给别人来帮助完 ...
- 为什么不能把委托(delegate)放在一个接口(interface)当中?
stackoverflow上有人问,为什么不能把委托放在一个接口当中? 投票最多的第一个答案第一句话说,“A Delegate is just another type, so you don't g ...
- C# 代理/委托 Delegate
本文转载自努力,努力,努力 1. 委托的定义:委托是函数的封装,它代表一"类"函数.他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数 ...
- 深入理解委托(Delegate)
前言 委托其实一直以来都感觉自己应该挺熟悉的,直到最近又去翻了翻 CLR via C#,感觉我之前的理解可能还有失偏颇.在这记录一下. 之前文章的链接: 接口和委托的泛型可变性 C#高级编程笔记 De ...
- C# -- 使用委托 delegate 执行异步操作
C# -- 使用委托 delegate 执行异步操作 委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似. 与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的. 委托的 ...
随机推荐
- 【数据库】MFC ODBC(四)
7.滚动记录 CRecordset提供了几个成员函数用来在记录集中滚动.当用这些函数滚动到一个新记录时,框架会自动地把新记录的内容拷贝到域数据成员中. void MoveNext( ); //前进一个 ...
- 201621123010《Java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 源代码阅读:多线程程序BounceThread 1.1 BallR ...
- chrome安装HostAdmin app
之前在chrome应用商店搜索HostAdmin App就可以搜到,最近发现搜不到了:可以按照下面的步骤进行安装. 1.找个安装有HostAdmin App的电脑,然后在chrome的扩展程序中找到它 ...
- L209
China's Chang'e-4 probe entered a planned orbit Sunday morning // to prepare for the first-ever soft ...
- 了解WCF的前世今生之实现服务端(一)
http://www.cnblogs.com/jiagoushi/archive/2013/03/15/2962351.html 1.WCF是对现有的分布式通信技术的一个整合,其中包括Com/DCom ...
- 前端开发 —— google chart 的使用
1. 引入所需的 js 库 在 <head></head>中 <script src="https://ajax.googleapis.com/ajax/lib ...
- Jenkins自动化部署代码
通过jenkins自动化部署项目代码可以大幅度节省打包上传部署的时间,提高开发测试的工作效率 ========== 完美的分割线 =========== 1.Jenkins是什么 1)Jenkins是 ...
- SW4STM32 全局宏定义
/************************************************************************************ * SW4STM32 全局宏 ...
- Binary file to C array(bin2c)
/******************************************************************************** * Binary file to C ...
- URL的应用
1.对于Android来说,开发应用都会去访问服务器地址,那么就要连网,需要通过URL. 先new一个URL来获取路径,然后利用HttpURLConnection来连接并打开url,并通过get 请求 ...