编程语言
首页 > 编程语言> > 【UE4 C++】<6>Delegate 委托

【UE4 C++】<6>Delegate 委托

作者:互联网


概念

定义

蓝图示例

image

声明委托

定义一个无参普通单播委托
DECLARE_DELEGATE( DelegateName )

定义一个无参普通单播委托, 带返回参数
DECLARE_DELEGATE_RetVal( ReturnValueType, DelegateName )

定义一个无参动态单播委托, 带返回参数
DECLARE_DYNAMIC_DELEGATE_RetVal

定义一个无参普通多播委托
DECLARE_MULTICAST_DELEGATE( DelegateName )

定义一个无参事件(特殊的多播委托)
DECLARE_EVENT( OwningType, EventName )

定义一个无参动态单播委托
DECLARE_DYNAMIC_DELEGATE( DelegateName)

定义一个无参动态多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE( DelegateName )

单播委托

声明宏

不支持返回,支持参数
DECLARE_DELEGATE_*
DECLARE_DELEGATE(DelegateName)
DECLARE_DELEGATE_OneParam(DelegateName, Param1Type)
DECLARE_DELEGATE_<Num>Params(DelegateName, Param1Type, Param2Type, ...)

支持返回RetValType,支持参数
DECLARE_DELEGATE_RetVal_*
DECLARE_DELEGATE_RetVal(RetValType, DelegateName) 
DECLARE_DELEGATE_RetVal_OneParam(RetValType, DelegateName, Param1Type) 
DECLARE_DELEGATE_RetVal_<Num>Params(RetValType, DelegateName, Param1Type, Param2Type, ...)

绑定委托

执行函数

用法示例

不带参数Delegate

//InventoryGameMode.h类外声明
DECLARE_DELEGATE(FStandardDelegateSignature)

//InventoryGameMode.h类成员声明变量
FStandardDelegateSignature MyStandardDelegate;

//DelegateListener.cpp绑定委托
MyInventoryGM->MyStandardDelegate.BindUObject(this, &ADelegateListener::EnableLight);
//DelegateListener.cpp解绑委托
MyInventoryGM->MyStandardDelegate.Unbind();

//MyTriggerVolume.cpp调用委托,间接调用函数
MyInventoryGM->MyStandardDelegate.ExecuteIfBound();

带参数Delegate

//InventoryGameMode.h类外声明
DECLARE_DELEGATE_OneParam(FParamDelegateSignature,FLinearColor)

//InventoryGameMode.h类成员声明变量
FParamDelegateSignature MyParamDelegate;

//ParamDelegateListener.cpp 绑定委托
MyInventoryGM->MyParamDelegate.BindUObject(this, &AParamDelegateListener::SetLightColor);
//ParamDelegateListener.cpp 解绑委托
MyInventoryGM->MyParamDelegate.Unbind();

//MyTriggerVolume.cpp调用委托,间接调用函数
auto Color = FLinearColor(1, 0, 0, 1);
MyInventoryGM->MyParamDelegate.ExecuteIfBound(Color);

传递有效负载数据

image


多播委托

声明宏

DECLARE_MULTICAST_DELEGATE(FMulticastDelegateSignature)
DECLARE_MULTICAST_DELEGATE_OneParam(FMulticastDelegateSignature, FString)

绑定多播委托

多播执行

用法示例

//InventoryGameMode.h类外声明
DECLARE_MULTICAST_DELEGATE(FMulticastDelegateSignature)

//InventoryGameMode.h类成员声明变量
FMulticastDelegateSignature MyMulticastDelegate;

//MulticastDelegateListener.h声明
FDelegateHandle MyDelegateHandle;
//MulticastDelegateListener.cpp 绑定委托
MyDelegateHandle = MyInventoryGM->MyMulticastDelegate.AddUObject(this, &AMulticastDelegateListener::ToggleLight);
//MulticastDelegateListener.cpp 解绑委托
MyInventoryGM->MyMulticastDelegate.Remove(MyDelegateHandle);

//MyTriggerVolume.cpp调用委托,间接调用函数
MyInventoryGM->MyMulticastDelegate.Broadcast();

//绑定lambda
FDelegateHandle Handle;
Handle=MDOneParam.AddLambda(
  [](FString str)
  {
    UE_LOG(LogTemp,Warning,TEXT("Lambda Call,Param Value:%s"),*str);
  }
)

动态委托

声明宏

动态多播代理的名称开头须为F,否则会编译或调用报错

DECLARE_DYNAMIC_DELEGATE_*
DECLARE_DYNAMIC_DELEGATE(FOnGameWindowCloseButtonClickedDelegate);  // 无参、无返回值
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnAssetLoaded, class UObject*, Loaded); // 1个参数、无返回值

DECLARE_DYNAMIC_DELEGATE_RetVal_*
DECLARE_DYNAMIC_DELEGATE_RetVal(EMouseCursor::Type, FGetMouseCursor); // 无参、EMouseCursor::Type返回值
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(UWidget*, FGenerateWidgetForObject, UObject*, Item); // 1个参数、UWidget*返回值
DECLARE_DYNAMIC_DELEGATE_RetVal_TwoParams(FEventReply, FOnPointerEvent, FGeometry, MyGeometry, const FPointerEvent&, MouseEvent);  // 2个参数、FEventReply返回值

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMyDelegate)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyDelegate, FString, InPrar)

DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FNotifyPawnChange, float, PawnHpPercent,float,PawnPhysicalShieldPercent,float, PawnMageShieldPercent);

动态委托绑定

动态多播也支持使用Remove和Removeall,用法与多播一样

执行动态委托

普通委托可以作为函数参数使用

//动态委托
DECLARE_DYNAMIC_DELEGATE(FWDE_Dy_Sl_Zero);

//委托变量作为参数
UFUNCTION(BlueprintCallable, Category = "FrameWork")
void RegFunDel(FWDE_Dy_Sl_Zero TargetFun);

动态多播委托

ECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FNotifyPawnChange, float, PawnHpPercent,float,PawnPhysicalShieldPercent,float, PawnMageShieldPercent);

UPROPERTY(BlueprintAssignable)
	FNotifyPawnChange NotifyPawnChange;

NotifyPawnChange.Broadcast(PawnHpPercent, PawnPhysicalShieldPercent, PawnMageShieldPercent);

事件

事件与 组播委托 十分相似。虽然任意类均可绑定事件,但只有声明事件的类可以调用事件 的 Broadcast、IsBound 和 Clear 函数。这意味着事件对象可在公共接口中公开,而无需让外部类访问这些敏感度函数。事件使用情况有:在纯抽象类中包含回调、限制外部类调用 Broadcast、IsBound 和 Clear 函数。

声明宏

DECLARE_EVENT( OwningType, EventName ) 创建一个事件。
DECLARE_EVENT_OneParam( OwningType, EventName, Param1Type ) 创建带一个参数的事件。
DECLARE_EVENT_TwoParams( OwningType, EventName, Param1Type, Param2Type ) 创建带两个参数的事件。 
DECLARE_EVENT_<Num>Params( OwningType, EventName, Param1Type, Param2Type, ...) 创建带 N 个参数的事件。

绑定事件

与多播委托方式相同

事件执行

事件允许附带多个函数委托,然后调用事件的 Broadcast() 函数将它们一次性全部执行。

用法示例

普通用法

//MyTriggerVolume.h 类外声明
DECLARE_EVENT(AMyTriggerVolume,FPlayerEntered)
//MyTriggerVolume.h 类内声明
FPlayerEntered OnPlayerEntered;

//MyTriggerVolume.cpp 调用委托
OnPlayerEntered.Broadcast();

//TriggerVolEventListener.cpp 绑定委托
TriggerEventSource->OnPlayerEntered.AddUObject(this, &ATriggerVolEventListener::OnTriggerEvent);

通常用法

将Event定义于类内,通常将Event对象设为私有,类外通过公开的访问接口进行绑定,触发,解绑,这种方式起到了保护隐私的作用

class ADelegateActor:public AActor
{
	GENERATED_BODY()
 public:
 	/*
    *OwingType:拥有此Event的类,本例中使用本类:ADelegateActor
    *EventName:事件名称
    *ParamType:参数列表
    */
	DECLARE_EVENT_OneParam(ADelegateActor, MyDelegateEvent, FString);

    //公开对Event对象的访问接口
   MyDelegateEvent& OnEventTrigger(){return DelegateEvent;}

 private:
 	//将Event设为私有,防止类外直接访问到,起到安全作用
  MyDelegateEvent DelegateEvent;
}
class CallbackTarget
{
 public:

  void FunctionForAddUObject(FString str);

  UFUNCTION()
  void FunctionForAddUFunction(FString str);
  //静态成员函数
  static StaticCallback(FString str)
  {
    UE_LOG(LogTemp,Warning,TEXT("StaticCallback Call,Param Value:%s"),*str);
  }
}
//全局静态函数(静态非成员函数)
void StaticFunc(FString str)
{
  UE_LOG(LogTemp,Warning,TEXT("StaticFunc Call,Param Value:%s"),*str);
}
CallbackTarget* Target=new CallbackTarget();
/*多播绑定回调函数以Add开头*/

//delegatehandle
FDelegateHandle Handle;

//AddUObject 绑定多播
Handle=OnEventTrigger().AddUObject(Target,&CallbackTarget::FunctionForAddUObject);

//AddUFunction 绑定多播
Handle=OnEventTrigger().AddUFunction(Target,FName(TEXT("FunctionForAddUFunction")));

//AddStatic 绑定全局静态函数
Handle=OnEventTrigger().AddStatic(StaticFunc);

//AddStatic 绑定静态成员函数
Handle=OnEventTrigger().AddStatic(&CallbackTarget::StaticCallback);

//AddLambda 绑定Lambda表达式
Handle=OnEventTrigger().AddLambda(
  [](FString str)
  {
    UE_LOG(LogTemp,Warning,TEXT("Lambda Call,Param Value:%s"),*str);
  }
)
OnEventTrigger().Broadcast("DELEGATE EVENT Call");
OnEventTrigger().Clear();

继承的抽象事件

基础类实现:

/** Register/Unregister a callback for when assets are added to the registry */
DECLARE_EVENT_OneParam( IAssetRegistry, FAssetAddedEvent, const FAssetData&);
virtual FAseetAddedEvent& OnAssetAdded() = 0;

派生类实现:

DECLARE_DERIVED_EVENT( FAssetRegistry, IAssetRegistry::FAssetAddedEvent, FAssetAddedEvent);
virtual FassetAddedEvent& OnAssetAdded() override { return AssetAddedEvent; }

在派生类中声明一个派生事件时,不要在 DECLARE_DERIVED_EVENT 宏中重复函数签名。此外,DECLARE_DERIVED_EVENT 宏的最后一个参数是事件的新命名,通常与基础类型相同。


参考

标签:多播,函数,委托,绑定,C++,Delegate,UE4,DECLARE,DELEGATE
来源: https://www.cnblogs.com/shiroe/p/14691192.html