原创文章,转载请注明出处。

## 今晚北京时间晚10点,虚幻官方发布UE5,内心是五笔的机动。

UE4有一套代理机制,整理了一下做个介绍。也请大家做补充。
有了代理,方便我们做代码设计,减轻耦合。

由于下面没有贴出全部代码,如果粘贴过去测试的话编译不过。所以我上传了一下,下载后对照更加一目了然。下载链接
针对不同的绑定我写了不同的类来演示。
文章介绍的目录比较深,不过也相对介绍全了用法。

代理汇总

  • 一.单播,不支持蓝图
    • 1.单播种类
      • 1>无参数&无返回值
      • 2>无参数&有返回值
      • 3>1-9个参数&无返回值
      • 4>1-9个参数&有返回值
    • 2.单播使用
      • 1>单播使用->定义
      • 2>单播使用->绑定
        • 单播使用->绑定->BindLambda Lambda表达式
        • 单播使用->绑定->BindWeakLambda Lambda表达式
        • 单播使用->绑定->BindRaw 原生C++函数
        • 单播使用->绑定->BindSP 智能指针函数(非线程安全版本,Fast模式版本)
        • 单播使用->绑定->BindThreadSafeSP 智能指针函数(线程安全版本,Safe)
        • 单播使用->绑定->BindStatic 静态方法
        • 单播使用->绑定->BindUFunction UFUNCTION()修饰的函数
        • 单播使用->绑定->BindUObject UObject类的函数
      • 3>单播使用->执行
      • 4>单播使用->解绑
  • 二.多播,不支持蓝图
    • 1.多播种类
      • 1>无参数
      • 2>1-9参数
    • 2.多播使用
      • 1>多播使用->定义
      • 2>多播使用->绑定
        • 多播使用->绑定->AddLambda Lambda表达式
        • 多播使用->绑定->AddWeakLambda Lambda表达式
        • 多播使用->绑定->AddRaw 原生C++函数
        • 多播使用->绑定->AddSP 智能指针函数(非线程安全版本,Fast模式版本)
        • 多播使用->绑定->AddThreadSafeSP 智能指针函数(线程安全版本,Safe)
        • 多播使用->绑定->AddStatic 静态方法
        • 多播使用->绑定->AddUFunction UFUNCTION()修饰的函数
        • 多播使用->绑定->AddUObject UObject类的函数
      • 3>多播使用->执行
      • 4>多播使用->解绑
  • 三.动态单播,不支持蓝图
    • 1.动态单播种类
      • 1>无参数&无返回值
      • 2>无参数&有返回值
      • 3>1-9个参数&无返回值
      • 4>1-9个参数&有返回值
    • 2.动态单播使用
      • 1>动态单播使用->定义
      • 2>动态单播使用->绑定
        • 动态单播使用->绑定->BindBindDynamic
      • 3>动态单播使用->执行
      • 4>动态单播使用->解绑
  • 四.动态多播,支持蓝图使用
    • 1.动态多播种类
      • 1>无参数
      • 2>1-9参数
    • 2.动态多播使用
      • 1>动态多播使用->定义
      • 2>动态多播使用->绑定
        • 动态多播使用->绑定->AddDynamic
      • 3>动态多播使用->执行
      • 4>多播使用->解绑
  • 五.事件, 可多态,不支持蓝图使用
    • 1.Event事件种类
    • 2.Event事件使用
      • 1>Event事件使用->定义
      • 2>Event事件使用->绑定
      • 3>Event事件使用->执行
      • 4>Event事件使用->解绑

文章里面的代码下载链接:
1>DelegateCombinations.h主要是代理的定义,这里头定义了 单播/多播/动态单播/动态多播/事件
的所有用法
2>Engine里面的CoreDelegates.h里面是一些引擎使用代理的地方,可以参考
3>如果你想做在代码里面被多处接收更新的,就用多播。这个也是GamePlay里面最多被用到的
4>如果你想和UMG控件/Component组件在蓝图右下角中可以添加事件的,就用动态多播
5>如果你想设计的漂亮,写个接口,用Event,但是不能被蓝图使用

一.单播,不支持蓝图

单播:顾名思义就是一次广播,只能通知到一个回调函数。
可以有返回值。如果重复调用绑定,将使用最后一个绑定的函数作为回调函数。

1.单播种类

1>无参数&无返回值

//(0参数)
DECLAR1E_DELEGATE(FDelegateSingleParm0);

2>无参数&有返回值

//(0参数, 有返回值类型为int32, 先写返回值, 在写代理名称)
DECLARE_DELEGATE_RetVal(int32, FDelegateSingleParm0WithRet);

3>1-9个参数&无返回值

//1参数, 参数写代理名称后头
DECLARE_DELEGATE_OneParam(FDelegateSingleParm1, int32);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……//9个参数的
DECLARE_DELEGATE_NineParams(FDelegateSingleParm9, int32, int32, int32, int32, int32, int32, int32, int32, int32);

4>1-9个参数&有返回值

//1参数, 参数写代理名称后头
DECLARE_DELEGATE_RetVal_OneParam(int32, FDelegateSingleParm1WithRet, int32);//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……//9个参数的
DECLARE_DELEGATE_RetVal_NineParams(int32, FDelegateSingleParm9WithRet, int32, int32, int32, int32, int32, int32, int32, int32, int32);

2.单播使用

1>单播使用->定义

//单播(也就是只能绑定一个函数)
//(0参数)
DECLARE_DELEGATE(FDelegateSingleParm0);
//(0参数, 有返回值类型为int32, 先写返回值, 在写代理名称)
DECLARE_DELEGATE_RetVal(int32, FDelegateSingleParm0WithRet);//1参数, 参数写代理名称后头
DECLARE_DELEGATE_OneParam(FDelegateSingleParm1, int32);
DECLARE_DELEGATE_RetVal_OneParam(int32, FDelegateSingleParm1WithRet, int32);//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……//9个参数的
DECLARE_DELEGATE_NineParams(FDelegateSingleParm9, int32, int32, int32, int32, int32, int32, int32, int32, int32);
DECLARE_DELEGATE_RetVal_NineParams(int32, FDelegateSingleParm9WithRet, int32, int32, int32, int32, int32, int32, int32, int32, int32);static FDelegateSingleParm0 DelegateSingleParm0;
static FDelegateSingleParm0WithRet DelegateSingleParm0WithRet;
static FDelegateSingleParm1 DelegateSingleParm1;
static FDelegateSingleParm1WithRet DelegateSingleParm1WithRet;
static FDelegateSingleParm9 DelegateSingleParm9;
static FDelegateSingleParm9WithRet DelegateSingleParm9WithRet;

2>单播使用->绑定

单播使用->绑定->BindLambda Lambda表达式

void ExcuteSingleParm0Lamdba()
{UUtilsLibrary::Log(TEXT("ExcuteSingleParm0Lamdba"));
}
int32 ExcuteSingleParm0WithRetLambda()
{UUtilsLibrary::Log(TEXT("ExcuteSingleParm0WithRetLambda"));return 1;
}//绑定Lambda表达式
FTestDelegates::DelegateSingleParm0.BindLambda([this]() { ExcuteSingleParm0Lamdba(); });
FTestDelegates::DelegateSingleParm0WithRet.BindLambda([this]() { return ExcuteSingleParm0WithRetLambda(); });

单播使用->绑定->BindWeakLambda Lambda表达式

BindWeakLambda 方法需要要在UObject类中使用,非继承自U类的是不能使用的。绑定Lambda表达式并且是持有UObject对象的弱引用

//这个方法我是写到继承自U类的方法里面的
FTestDelegates::DelegateSingleParm0.BindWeakLambda(this, [this]() { OnExcuteSingleParm0Lamdba(); });

单播使用->绑定->BindRaw 原生C++函数

FTestDelegates::DelegateSingleParm0.BindRaw(this, &CTestRaw::ExcuteSingleParm0);
//FTestDelegates::DelegateSingleParm0.BindRaw(this, &CTestRaw::ExcuteSingleParm01111);  //重复绑定会用最后的函数
FTestDelegates::DelegateSingleParm0.BindStatic(&hhh12312312);                           //重复绑定会用最后的函数
FTestDelegates::DelegateSingleParm0WithRet.BindRaw(this, &CTestRaw::ExcuteSingleParm0WithRet);
FTestDelegates::DelegateSingleParm1.BindRaw(this, &CTestRaw::ExcuteSingleParm1);
FTestDelegates::DelegateSingleParm1WithRet.BindRaw(this, &CTestRaw::ExcuteSingleParm1WithRet);
FTestDelegates::DelegateSingleParm9.BindRaw(this, &CTestRaw::ExcuteSingleParm9);
FTestDelegates::DelegateSingleParm9WithRet.BindRaw(this, &CTestRaw::ExcuteSingleParm9WithRet);

单播使用->绑定->BindSP 智能指针函数(非线程安全版本,Fast模式版本)

我这个里面的测试代码,文章开头有链接可以提供下载,可以直接下载下来看更直观。
注意类的书写方式,继承自public TSharedFromThis<CTestNotSafeSharePoint, ESPMode::Fast>

//测试单播绑定智能指针,FastMode, 非线程安全版本
class CTestNotSafeSharePoint : public TSharedFromThis<CTestNotSafeSharePoint, ESPMode::Fast>
{}
//绑定智能指针,FastMode, 非线程安全
FTestDelegates::DelegateSingleParm0.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm0);
FTestDelegates::DelegateSingleParm0WithRet.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm0WithRet);
FTestDelegates::DelegateSingleParm1.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm1);
FTestDelegates::DelegateSingleParm1WithRet.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm1WithRet);
FTestDelegates::DelegateSingleParm9.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm9);
FTestDelegates::DelegateSingleParm9WithRet.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm9WithRet);

单播使用->绑定->BindThreadSafeSP 智能指针函数(线程安全版本,Safe)

//注意类的书写方式,继承自public TSharedFromThis<CTestNotSafeSharePoint, ESPMode::ThreadSafe>

//测试单播绑定智能指针,ThreadSafe, 线程安全版本
class CTestSafeSharePoint : public TSharedFromThis<CTestSafeSharePoint, ESPMode::ThreadSafe>
{};
//绑定智能指针,ThreadSafe,线程安全版本
FTestDelegates::DelegateSingleParm0.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm0);
FTestDelegates::DelegateSingleParm0WithRet.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm0WithRet);
FTestDelegates::DelegateSingleParm1.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm1);
FTestDelegates::DelegateSingleParm1WithRet.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm1WithRet);
FTestDelegates::DelegateSingleParm9.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm9);
FTestDelegates::DelegateSingleParm9WithRet.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm9WithRet);

单播使用->绑定->BindStatic 静态方法

//用来测试的静态函数
static void MyTestStaticFunc()
{UUtilsLibrary::Log(TEXT("static function MyTestStaticFunc"));
}
FTestDelegates::DelegateSingleParm0.BindStatic(&MyTestStaticFunc);

单播使用->绑定->BindUFunction UFUNCTION()修饰的函数

注意,你的方法一定是要被UFUNCTION()所修饰的

//this, 字符串(函数名称)
FTestDelegates::DelegateSingleParm1.BindUFunction(this, "OnExcuteSingleParm1");
FTestDelegates::DelegateSingleParm1WithRet.BindUFunction(this, "OnExcuteSingleParm1WithRet");

单播使用->绑定->BindUObject UObject类的函数

顾名思义,就是我们这个方法要定义在U类的派生类上。不需要加UFUNCTION()标记

//BindUObject测试
FTestDelegates::DelegateSingleParm0.BindUObject(this, &AMyDelegateTestActor::OnExcuteSingleParm0);
FTestDelegates::DelegateSingleParm0WithRet.BindUObject(this, &AMyDelegateTestActor::OnExcuteSingleParm0WithRet);

3>单播使用->执行

void MyExecue()
{int32 nParam = 1;int32 nRet = 2;FTestDelegates::DelegateSingleParm0.ExecuteIfBound();if (FTestDelegates::DelegateSingleParm0WithRet.IsBound())nRet = FTestDelegates::DelegateSingleParm0WithRet.Execute();FTestDelegates::DelegateSingleParm1.ExecuteIfBound(nParam);if (FTestDelegates::DelegateSingleParm1WithRet.IsBound())nRet = FTestDelegates::DelegateSingleParm1WithRet.Execute(nParam);FTestDelegates::DelegateSingleParm9.ExecuteIfBound(nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam);if (FTestDelegates::DelegateSingleParm9WithRet.IsBound())nRet = FTestDelegates::DelegateSingleParm9WithRet.Execute(nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam);
}

4>单播使用->解绑

void CanelBind()
{FTestDelegates::DelegateSingleParm0.Unbind();FTestDelegates::DelegateSingleParm0WithRet.Unbind();FTestDelegates::DelegateSingleParm1.Unbind();FTestDelegates::DelegateSingleParm1WithRet.Unbind();FTestDelegates::DelegateSingleParm9.Unbind();FTestDelegates::DelegateSingleParm9WithRet.Unbind();
}

二.多播,不支持蓝图

单播:顾名思义就是一次广播,通知到多个回调函数上。
和单播不同,多播是没有返回值的。
多播每次绑定的函数都会在广播的时候进行调用,所以也要注意不要重复绑定, 用好解绑和绑定方法。

1.多播种类

1>无参数

//不带参数的多播
DECLARE_MULTICAST_DELEGATE(FDelegateMulticastNoParam);

2>1-9参数

//带有1个参数的多播
DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateMulticastParam1, int32);
///...2-8个参数的可以自己写一下
//带有9个参数的多播
DECLARE_MULTICAST_DELEGATE_NineParams(FDelegateMulticastParam9, int32, int32, int32, int32, int32, int32, int32, int32, int32);

2.多播使用

1>多播使用->定义

//不带参数的多播
DECLARE_MULTICAST_DELEGATE(FDelegateMulticastNoParam);
//带有1个参数的多播
DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateMulticastParam1, int32);
///...2-8个参数的可以自己写一下
//带有9个参数的多播
DECLARE_MULTICAST_DELEGATE_NineParams(FDelegateMulticastParam9, int32, int32, int32, int32, int32, int32, int32, int32, int32);static FDelegateMulticastNoParam DelegateMulticastNoParam;
static FDelegateMulticastParam1 DelegateMulticastParam1;
static FDelegateMulticastParam9 DelegateMulticastParam9;

2>多播使用->绑定

和单播的方法是类似的,区别就是单播叫Bind,多播叫Add,也很容易理解。多播是支持多个回调广播的。

多播使用->绑定->AddLambda Lambda表达式

FTestDelegates::DelegateMulticastNoParam.AddLambda([this]() { OnExcuteSingleParm0Lamdba(); });

多播使用->绑定->AddWeakLambda Lambda表达式

AddWeakLambda 方法需要要在UObject类中使用,非继承自U类的是不能使用的。绑定Lambda表达式并且是持有UObject对象的弱引用

FTestDelegates::DelegateMulticastNoParam.AddWeakLambda(this, [this]() { OnExcuteSingleParm0Lamdba(); });

多播使用->绑定->AddRaw 原生C++函数

FTestDelegates::DelegateMulticastNoParam.AddRaw

多播使用->绑定->AddSP 智能指针函数(非线程安全版本,Fast模式版本)

FTestDelegates::DelegateMulticastNoParam.AddSP

多播使用->绑定->AddThreadSafeSP 智能指针函数(线程安全版本,Safe)

FTestDelegates::DelegateMulticastNoParam.AddThreadSafeSP

多播使用->绑定->AddStatic 静态方法

FTestDelegates::DelegateMulticastNoParam.AddStatic

多播使用->绑定->AddUFunction UFUNCTION()修饰的函数

FTestDelegates::DelegateMulticastNoParam.AddUFunction

注意,你的方法一定是要被UFUNCTION()所修饰的

多播使用->绑定->AddUObject UObject类的函数

FTestDelegates::DelegateMulticastNoParam.AddUObject

3>多播使用->执行

调用Broadcast

FTestDelegates::DelegateMulticastNoParam.Broadcast(/*your params here*/);

4>多播使用->解绑

单个解绑、整体解绑。
比如在类中使用的时候,如在A类里面使用的时候,建议在Beginplay等方法开始绑定,在EndPlay解除绑定。

//多播绑定
FDelegateHandle m_Delegate1 = FTestDelegates::DelegateMulticastNoParam.AddLambda([this]() { OnExcuteSingleParm0Lamdba(); });
FDelegateHandle m_Delegate2 = FTestDelegates::DelegateMulticastNoParam.AddWeakLambda(this, [this]() { OnExcuteSingleParm0Lamdba(); });//多播解绑->单个函数解绑
FTestDelegates::DelegateMulticastNoParam.Remove(m_Delegate1);
FTestDelegates::DelegateMulticastNoParam.Remove(m_Delegate2);//全部解绑
FTestDelegates::DelegateMulticastNoParam.Clear();

三.动态单播,不支持蓝图

单播:顾名思义就是一次广播,只能通知到一个回调函数。
1>Notes:可以有返回值。如果重复调用绑定,将使用最后一个绑定的函数作为回调函数。
2>Notes:被绑定函数必须要有UFUNCTION()修饰,否则会崩溃
3>Notes:必须要写在序列化的文件里面, 也就是.generated.h的文件中
4>Notes:因为支持序列化,所以参数名字也要写上,不同于上面的非动态代理只需要定义类型即可,这个还需要定义好参数名称

1.动态单播种类

1>无参数&无返回值

//(0参数)
DECLARE_DYNAMIC_DELEGATE(FDelegateDynamicSingleNoParam);

2>无参数&有返回值

//(0参数, 有返回值类型为int32, 先写返回值, 在写代理名称)
DECLARE_DYNAMIC_DELEGATE_RetVal(int32, FDelegateDynamicSingleNoParamWithRet);

3>1-9个参数&无返回值

//1参数, 参数写代理名称后头
DECLARE_DYNAMIC_DELEGATE_OneParam(FDelegateDynamicSingleParm1, int32, param1);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……
//9个参数的
DECLARE_DYNAMIC_DELEGATE_NineParams(FDelegateDynamicSingleParm9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

4>1-9个参数&有返回值

//1参数, 参数写代理名称后头
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(int32, FDelegateDynamicSingleParm1WithRet, int32, param1);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……
//9个参数的
DECLARE_DYNAMIC_DELEGATE_RetVal_NineParams(int32, FDelegateDynamicSingleParm9WithRet, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

2.动态单播使用

1>动态单播使用->定义

具体写法参考上面单播就行

DECLARE_DYNAMIC_DELEGATE(FDelegateDynamicSingleNoParam);
//1参数, 参数写代理名称后头
DECLARE_DYNAMIC_DELEGATE_OneParam(FDelegateDynamicSingleParm1, int32, param1);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……
//9个参数的
DECLARE_DYNAMIC_DELEGATE_NineParams(FDelegateDynamicSingleParm9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);FDelegateDynamicSingleNoParam DelegateDynamicSingleNoParam;
FDelegateDynamicSingleNoParamWithRet DelegateDynamicSingleNoParamWithRet;

2>动态单播使用->绑定

动态单播使用->绑定->BindBindDynamic

调用BindBindDynamic进行绑定即可,并且记住绑定的函数一定是有UFUNCTION()修饰的.
后绑定会覆盖前面的绑定,因为是单播

DelegateDynamicSingleNoParam.BindDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicSingleNoParam);

3>动态单播使用->执行

调用ExecuteIfBound比较安全,如果直接调用Execute没有绑定的话会引发断言崩溃。

DelegateDynamicSingleNoParam.ExecuteIfBound();

4>动态单播使用->解绑

直接调用.Clear()清除绑定

DelegateDynamicSingleNoParam.Clear();

四.动态多播,支持蓝图使用

‘BlueprintAssignable’ is only allowed on multicast delegate properties
'BlueprintAssignable’只允许在多播委托属性上使用
单播:顾名思义就是一次广播,通知到多个回调函数上。
和动态单播不同,动态多播是没有返回值的。
像UMG控件还有很多组件在蓝图中右下角可以添加事件,就是通过这个动态多播实现的
函数必须强制加UFUNCTION()宏, 否则运行时会报错 引发断言崩溃掉
动态多播每次绑定的函数都会在广播的时候进行调用,所以也要注意不要重复绑定, 用好解绑和绑定方法。

1.动态多播种类

1>无参数

//不带参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDelegateDynamicMulticastNoParam);

2>1-9参数

//带有1个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDelegateDynamicMulticastParam1, int32, param1);
//中间省略2-8个参数的多播
//带有9个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_NineParams(FDelegateDynamicMulticastParam9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

2.动态多播使用

1>动态多播使用->定义

//不带参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDelegateDynamicMulticastNoParam);
//带有1个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDelegateDynamicMulticastParam1, int32, param1);
//中间省略2-8个参数的多播
//带有9个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_NineParams(FDelegateDynamicMulticastParam9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);FDelegateDynamicMulticastNoParam DelegateDynamicMulticastNoParam;
FDelegateDynamicMulticastParam1 DelegateDynamicMulticastParam1;
FDelegateDynamicMulticastParam9 DelegateDynamicMulticastParam9;

2>动态多播使用->绑定

和动态单播的方法是类似的,区别就是单播叫Bind,多播叫Add,也很容易理解。多播是支持多个回调广播的。

动态多播使用->绑定->AddDynamic

DelegateDynamicMulticastNoParam.AddDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicMulticastNoParam);
DelegateDynamicMulticastNoParam.AddDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicMulticastNoParam2);

3>动态多播使用->执行

调用Broadcast

DelegateDynamicMulticastNoParam.Broadcast(/*your params here*/);

4>多播使用->解绑

//方式1 清空所有绑定

DelegateDynamicMulticastNoParam.Clear();

//方式2 清空单个,按函数地址

DelegateDynamicMulticastNoParam.RemoveDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicMulticastNoParam2);

//方式3 清空单个, 按字符串

DelegateDynamicMulticastNoParam.Remove(this, TEXT("FuncDelegateDynamicMulticastNoParam"));

五.事件, 可多态,不支持蓝图使用

** 不允许写在A类里面**
** 允许写在U类里面和F类里面**
** 和多播一样,可以绑定多个回调函数**
** 多态关键字 DECLARE_DERIVED_EVENT***
事件,绑定用法和单播一样,但是它可以进行多播。并且可以设计成可被继承的代理,引擎里面有很多地方都在这么使用。

介绍一下如何实现事件的继承
** DECLARE_DERIVED_EVENT***

1.Event事件种类

DECLARE_EVENT 无参数
DECLARE_EVENT_OneParam 1个参数
//2-8个参数的就不一一列出来了,去DelegateCombinations.h中查阅
DECLARE_EVENT_NineParams 9个参数

2.Event事件使用

1>Event事件使用->定义

首先,我做了一个接口类,方法是纯虚函数,然后在我的F类里面做继承测试(也可以是U类,但是不可以是带有反射信息的A类)
//第一个参数:属于的类名
//第二个参数:Event名称
//后续的参数:就是填的params了
DECLARE_EVENT(IMyEvents, FMySocketConnectedEvent);
…………

//用来演示代理里面Event的继承
//用来演示代理里面Event的继承
class IMyEvents
{public:virtual ~IMyEvents(){ }DECLARE_EVENT_OneParam(IMyEvents, FMySocketMessageEvent, const FString& /* MessageString */);virtual FMySocketMessageEvent& OnMessage() = 0;
};

下面是继承类实现


//Event测试类
class CTestEvent : public IMyEvents, public TSharedFromThis<CTestEvent, ESPMode::ThreadSafe>
{public://Events测试void OnExcuteEventCTestEventOnRawMessage(const FString&){UUtilsLibrary::Log(TEXT("Safe SharePoint OnExcuteEventCTestEventOnRawMessage"));}DECLARE_DERIVED_EVENT(FLwsMySocket, IMyEvents::FMySocketMessageEvent, FMySocketMessageEvent);virtual FMySocketMessageEvent& OnMessage() override{return MessageEvent;}FMySocketMessageEvent MessageEvent;void BindAndExcute(){//OnMessage().AddLambda//OnMessage().AddRaw//OnMessage().AddSP//OnMessage().AddStatic//OnMessage().AddThreadSafeSP//OnMessage().AddUFunction//OnMessage().AddUObject//OnMessage().AddWeakLambdam_Delegate1 = OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);OnMessage().Broadcast(TEXT("test event"));}void CanelBind(){OnMessage().Clear();OnMessage().Remove(m_Delegate1);//OnMessage().RemoveAll()}~CTestEvent(){CanelBind();}FDelegateHandle m_Delegate1;
};

2>Event事件使用->绑定

//OnMessage().AddLambda
//OnMessage().AddRaw
//OnMessage().AddSP
//OnMessage().AddStatic
//OnMessage().AddThreadSafeSP
//OnMessage().AddUFunction
//OnMessage().AddUObject
//OnMessage().AddWeakLambda
OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);

3>Event事件使用->执行

调用Broadcast

MessageEvent.Broadcast(TEXT("test event"));

4>Event事件使用->解绑

//第一种方式 清空全部绑定

OnMessage().Clear();

//第二种方式 清空单个绑定

m_Delegate1 = OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
OnMessage().Remove(m_Delegate1);

第三种方式

OnMessage().RemoveAll()

谢谢,创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 <( ̄︶ ̄)>

UE4/UE5 代理使用介绍相关推荐

  1. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 ALS V4地面站立动作状态机详解

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的 ...

  2. [玩转UE4/UE5动画系统>Control Rig篇] 之 Control Rig + Fullbody IK版的足部IK实现(附项目代码)

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的资 ...

  3. UE4 /UE5 PC/安卓优化

    一.概述 UE4/UE5场景中的资源越多,消耗的内存就越大,就会越卡顿.这里教大家如何进行场景优化,来减少内存,使得场景更加流畅. 二.模型优化 2.1.使用3Dmax或者Maya制作的模型,面数最好 ...

  4. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 ALS V4 主状态机详解

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的 ...

  5. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 布娃娃系统(ALS V4实现方案详解)

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式. 教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>. 教程中使 ...

  6. 【虚幻引擎】UE4/UE5鼠标点击事件实现物体移动

    B站教学链接:https://space.bilibili.com/449549424?spm_id_from=333.1007.0.0 一.原理解析 在UE4/UE5中,引擎有它自己的一套框架体系, ...

  7. 在 Lotus Notes 中设置邮件定时发送的方法及代理功能介绍

    孙 茂伟, 测试工程师, IBM 孙茂伟在北京科技大学获得工学学士.工学硕士学位,现于 IBM CDL ECM FileNet EForms TEAM 从事自动化测试相关工作. 简介: 本文将向广大 ...

  8. blender 保留贴图转换 mmd 模型到 ue4/ue5 引擎

    本以为自己记忆力不错,然而真实是时间一长就把细节忘了,细节忘了又要折腾半天... 连操作面板都忘了在哪了,gg. 时间标记:2021/8/14 工具版本 blender 2.93.1 blender_ ...

  9. [玩转UE4/UE5动画系统>Control Rig篇] 之 使用Control Rig实现目标偏移(Aim Offset)(附项目代码)

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的资 ...

最新文章

  1. Nature Chemistry | 化学机器学习的最佳实践:推荐的一套标准化指南
  2. 记录一下:使用 python -m SimpleHTTPServer 快速搭建http服务
  3. 【Python】从文件中读取数据
  4. Stanford UFLDL教程 逻辑回归的向量化实现样例
  5. java 按条件注解_Spring 条件注解 @Conditional
  6. 8086CPU写汇编的规则
  7. python报数组越界_python数组越界
  8. 不要错过这轮疫情的“洗牌”机会
  9. es6 循环加载ES6模块
  10. poj 1847 Tram 最短路 dijkstra、floyed
  11. Direct3d 显示视频的一个问题
  12. 连接linux系统的mysql,Linux系统MySQL开启远程连接
  13. 客机客座率达到多少,航空公司才能不赔钱
  14. cassandra写数据CommitLog
  15. Fortran入门教程(十)——结构体
  16. 上海富勒wms_国内WMS前三名是哪几家
  17. 【初级篇】使得PC搭建的网站在非局域网也能访问的几种方法
  18. sendgrid html text,包括里面sendgrid鄂麦邮件的内容我的HTML代码
  19. CARLA 笔记(02)— Ubuntu 安装 CARLA(服务端、客户端、安装 miniconda、创建虚拟环境、更换 pip 源、生成交通流、人工控制车辆按键)
  20. 如何更改计算机c盘中用户名,windows10家庭版怎么更改c盘中的用户名_win10家庭版修改c盘用户名操作方法...

热门文章

  1. 虚拟机安装64位操作系统
  2. 记录我的java之路——day26(周更)
  3. 对于Markdown文件的一些编辑方法说明
  4. S50 Mifare卡块操作控制权限
  5. NAND Flash和 NOR Flash的区别
  6. SFDC安装第三方Packages的注意事项
  7. 大康Dacom Athlete+蓝牙耳机与手机配对上的原因及解决办法:
  8. 详细盘点清华姚班 智班,北大 浙大图灵班等多所高校AI专业实力!
  9. 沃拼图游戏软件测试,拼图游戏测试报告
  10. SQL85 实习广场投递简历分析(二)