UE4里的Delegate

Delegate的本质是回调,是观察者模式的应用。

A里产生变化需要与A1,A2,A3有交互。有3种方式:

方式1:A里调用A1, A2,A3的方法。

方式2:A1, A2, A3里调用A的方法。

方式3:弄一个中间者,Event/Delegate,A不用知晓A1, A2,A3的存在,A1,A2,A3也不用知道A的存在(Event/Delegate可以不用放在A里,另外放在另一个类里也没问题)。 A1, A2,A3里往Event/Delegate里添加回调函数。

方式1和方式2写得比较随意简单,增加了耦合度。但对于代码中很少用到的函数调用,且本身A1,A2,A3已经有了依赖于A的耦合度了,不妨直接调用,简单有效。

方式3的写法比较正规,可以完全解耦。

 

举例说明:

AudioManager里提供了接口:

void PreLoadBankByWeapon(int32 WeaponID)

void UnLoadBankByWeapon(int32 WeaponID)

因为AudioManager相对而言更底层,不会依赖上层的WeaponSys。 WeaponSys可以依赖AudioManager,毕竟需要调用AudioManager提供的PostEvent(***)等音频播放函数。

因此业务系统调用这两个接口有可选的两种方式:

1) WeaponSys里在需要的地方直接调用。

2) WeaponSys在需要的地方抛出Event/Delegate, AudioManager往Event/Delegate里注册这两个接口函数作为回调。

这两个方式都可以,看业务系统觉得怎么方便吧。负责WeaponSys的同事觉得直接调用AudiaoManager里的函数更方便,免去了加Event/Delegate的麻烦。 负责任务系统的同事则不喜欢直接调用,加的Event/Delegate有通用性,除了给AudiaoManager使用还可以给其他有需要的使用。

 

 

理解Delegate/Event,只需要把握3点:

1. Delegate/Event可绑定多个函数还是单个函数。

2. Delegate/Event的触发。

3. Delegate/Event回调函数的绑定。

看UE4里的Delegate/Event,则看3点:

1. Delegate/Event的声明。

UE4里Delegate/Event的声明,偏重于3点:

1) 单播 vs 多播 MULTICAST 带有"MULTICAST"的为多播,无则为单播。

2) 静态 vs 动态 DYNAMIC DYNAMIC意味着会添加到反射系统,可以供蓝图使用供Lua使用。

3) 是否有参数。

2. Delegate/Event的触发。

UE4里的Event其实是受限的Delegate,Event只能由自身触发,普通的Delegate无此限制。

单播的触发用Execute(***) ExecuteIfBound(***), 若Delegate/Event里有参数则参数带上。单播需要判断IsBound()。

多播的触发使用Broadcast(***), 若Delegate/Event里有参数则参数带上。多播无需判断IsBound()。

3. Delegate/Event回调函数的绑定。

 

静态动态 单播多播 2*2, 4种排列组合。

 

静态单播

//声明

DECLARE_DELEGATE_OneParam(MyIntDelegate, int32)

MyIntDelegate IntDelegate;

//绑定 --BindUObject与BindUFunction均可,更推荐BindUObject

IntDelegate.BindUFunction(this, FName("IntFunction"));

IntDelegate.BindUObject(this, &UTheClass::IntFunction); //更推荐

//调用

IntDelegate.Execute(999); // or IntDelegate.ExecuteIfBound(999);

 

静态多播

//声明

DECLARE_MULTICAST_DELEGATE_OneParam(MyIntDelegate, int32)

MyIntMulticastDelegate IntMulticastDelegate;

//绑定 --AddUObject与AddUFunction均可,更推荐AddUObject

IntMulticastDelegate.AddUFunction(this, FName("IntFunction"));

IntMulticastDelegate.AddUFunction(this, FName("SecondIntFunction"));

IntMulticastDelegate.AddUFunction(this, FName("ThirdIntFunction"));

IntDelegate.AddUObject(this, &UTheClass::IntFunction); //更推荐

//调用

IntMulticastDelegate.Broadcast(123);

 

动态单播

//声明

DECLARE_DYNAMIC_DELEGATE_TwoParams(FMyIntDel, int32, iCount);

//绑定 --只有BindDynamic

MyIntDel.BindDynamic(this, &UTheClass::IntFunction)

//调用

MyIntDel.ExecuteIfBound(123);

 

动态多播

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FMyDel, int32, iCount, float, fHeight);

//绑定 --只有AddDynamic

MyDel.AddDynamic(this, &UTheClass::MyFunction)

//调用

MyDel.Broadcast(123, 3.14f);

 

 

完整的示例

//TDHintSys.h
//静态单播
DECLARE_DELEGATE_OneParam(FMySingleDelegate, int32);
//动态单播
DECLARE_DYNAMIC_DELEGATE_OneParam(FMySingleDynamicDelegate, int32, iYearCount);
//静态多播
DECLARE_MULTICAST_DELEGATE_TwoParams(FMyMultiDelegate, int32, float);
//动态多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FMyMultiDynamicDelegate, int32, iYearCount, float, fHeight);

UFUNCTION(Exec)void IvyTestDel(int32 arg);
	
	void OnMySingle(int32 val);
	UFUNCTION() void OnMySingleUFunc(int32 val);

	void OnMySingleDynamic(int32 iYearCount);
	UFUNCTION() void OnMySingleDynamicUFunc(int32 iYearCount);

	void OnMyMulti(int32 iYearCount, float fHeight);
	UFUNCTION() void OnMyMultiUFunc(int32 iYearCount, float fHeight);

	void OnMyMultiDynamic(int32 iYearCount, float fHeight);
	UFUNCTION() void OnMyMultiDynamicUFunc(int32 iYearCount, float fHeight);

 

//TDHintSys.cpp
void UTDHintSys::IvyTestDel(int32 arg)
{
	switch(arg)
	{
	case 1:
	{
		FMySingleDelegate Del;
		Del.BindUObject(this, &UTDHintSys::OnMySingle);
		Del.ExecuteIfBound(arg);
		break;
	}
	case 2:
	{
		FMySingleDelegate Del;
		Del.BindUObject(this, &UTDHintSys::OnMySingleUFunc);
		Del.ExecuteIfBound(arg);
		break;
	}
	case 3:     
	{
		FMySingleDelegate Del;
		Del.BindUFunction(this, FName("OnMySingle"));  //cause to crash 
		Del.ExecuteIfBound(arg);
		break;
	}
	case 4:
	{
		FMySingleDelegate Del;
		Del.BindUFunction(this, FName("OnMySingleUFunc"));
		Del.ExecuteIfBound(arg);
		break;
	}

	case 11:
	{
		FMyMultiDelegate Del;
		Del.AddUObject(this, &UTDHintSys::OnMyMulti);
		Del.Broadcast(arg, 3.14f);
		break;		
	}
	case 12:
	{
		FMyMultiDelegate Del;
		Del.AddUObject(this, &UTDHintSys::OnMyMultiUFunc);
		Del.Broadcast(arg, 3.14f);
		break;
	}
	case 13:
	{
		FMyMultiDelegate Del;
		Del.AddUFunction(this, FName("OnMyMulti")); //cause to crash 
		Del.Broadcast(arg, 3.14f);
		break;
	}
	case 14:
	{
		FMyMultiDelegate Del;
		Del.AddUFunction(this, FName("OnMyMultiUFunc"));		
		Del.Broadcast(arg, 3.14f);
		break;
	}

	case 21:
	{
		FMyMultiDynamicDelegate Del;
		Del.AddDynamic(this, &UTDHintSys::OnMyMultiDynamicUFunc);
		Del.Broadcast(arg, 3.14f);
		break;
	}
	case 22:
	{
		FMyMultiDynamicDelegate Del;
		Del.AddDynamic(this, &UTDHintSys::OnMyMultiDynamic); //cause to crash 
		Del.Broadcast(arg, 3.14f);
		break;
	}

	case 31:
	{
		FMySingleDynamicDelegate Del;
		Del.BindDynamic(this, &UTDHintSys::OnMySingleDynamicUFunc);
		Del.ExecuteIfBound(arg);
		break;
	}
	case 32:
	{
		FMySingleDynamicDelegate Del;
		Del.BindDynamic(this, &UTDHintSys::OnMySingleDynamic);//cause to crash 
		Del.ExecuteIfBound(arg);
		break;
	}

	default:
		break;
	}
}

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值