[UE4]Event, Delegate, Multi-cast Related
keywords: [UE4]Event, Delegate, Multi-cast Related
keywords:UE4, BindRaw, BindUFunction, BindUObject, Pass Arguments, Variable
Examples
Delegate示例(BindUFunction传递参数)
示例1:
void UMyClass::FunctionWithVar(const FString& MyVar, TFunction<void(const FString&)> InFunction)
{
MyLambdaHandle = OnMyDelegate.BindStatic([MyVar](TFunction<void(const FString&)> callback) {callback(MyVar);}, InFunction);
// TODO: You have to track MyLambdaHandle to be able to unregister it when needed
}
https://answers.unrealengine.com/questions/715835/bindufunction-with-variable-capture-in-c.html
示例2:
使用固定参数绑定
DECLARE_DELEGATE(RefreshOne);
class MyClass
{
public:
MyClass()
{
one.BindRaw(this, &MyClass::MyFunction, (uint8)1);
}
void MyFunction(uint8 Val)
{
// Whatever
}
void Invoke()
{
one.Execute(); // Will call this->MyFunction((uint8)1);
}
private:
RefreshOne one;
};
使用动态参数绑定
DECLARE_DELEGATE_TwoParams(Delegate, const TCHAR*, float);
struct MyClass
{
MyClass()
{
del.BindRaw(this, &MyClass::MyFunction, (uint8)1, 'x');
}
void MyFunction(const TCHAR* a, float b, uint8 c, char d)
{
// Whatever
}
void Invoke()
{
del.Execute(TEXT("Hello"), 3.14f); // Will call this->MyFunction(TEXT("Hello"), 3.14f, (uint8)1, 'x');
}
Delegate del;
};
Bind delegate with one parameter
https://answers.unrealengine.com/questions/109955/bind-delegate-with-one-parameter.html
Event示例
Define:
UCLASS()
class MYPROJ_API AMyGameMode : public AGameMode
{
GENERATED_BODY()
public:
AHGameMode();
//定义Event
DECLARE_EVENT(MyUObject, MyInitEvent)
//定义带参数的Event
//DECLARE_EVENT_OneParam(MyUObject, MyInitEvent, FMyStruct*)
//用于获取Event引用的函数,方便在GameMode之外执行binding
MyInitEvent& OnInitialize() { return InitEvent; }
private:
//Event实例化
MyInitEvent InitEvent;
//Event的binding指针
FDelegateHandle DHandle;
}
Binding:
MyUObject* MyObj = nullptr; //这里假设创建MyUObject
if (MyObj)
{
DHandle = MyGameMode->OnInitialize().AddUObject(MyObj, &MyUObject::TestFun);
}
Boradcast:
void AMyGameMode::BeginPlay()
{
InitEvent.Broadcast();
}
Unbinding:
MyGameMode->OnInitialize().Remove(DHandle);
Difference
BindRaw、BindUObject、BindUFunction区别
- BindRaw():针对非UObject类型的class。
- BindUObject():针对UObject类型Class的非UFUNCTION()函数。
- BindUFunction:针对UObject类型Class的UFUNCTION()函数。
BindRaw 示例:
FTimerDelegate TimerDel;
TimerDel.BindRaw(this, &MyClass::MyFunction);
BindUObject 示例:
FTimerDelegate TimerDel;
TimerDel.BindUObject(this, &AMyCharacter::MyUFunction);
BindUFunction 示例:
TimerDel.BindUFunction(this, FName("TestFun"));
TScriptDelegate 与 DECLARE_DELEGATE 区别
引擎提供了两种用于绑定函数的代理对象:
- FScriptDelegate
- FMulticastScriptDelegate
这两种对象只能使用BindUFunction
一种方式绑定,因为他们使用的是DECLARE_DYNAMIC_MULTICAST_DELEGATE
,这种代理对象支持转化为stream,可以在网络中传递。
FTimerDelegate 之所以能有三种方式绑定,是因为它是由DECLARE_DELEGATE
定义。
Event 和 Delegate 区别
- Delegate 只能绑定一个回调函数,Delegate执行Execute()函数时,只会触发事先绑定的一个函数;Event可以绑定任意个函数,一旦执行Event的Broadcast()函数,所有回调函数按Add顺序依次执行。
- Dynamic Multicast Delegate也可以同时绑定多个回调函数,但是其运行效率要比 Event 慢。
- Event没有返回值,而Delegate可以,例如:
DECLARE_DELEGATE_RetVal_OneParam( ReturnValueType, DelegateName, Param1Type )
。
注意:UE早期版本两者都没有返回值。
Dynamic Delegate 与 常规 Delegate 区别
-
Dynamic Delegates 可以被序列化:即他们的注册函数可以通过名称查找获取,代价是比普通Delegate速度慢。
-
普通Delegate定义参数时,如果使用引用类型,函数执行时传递的实际参数无效,如果要使用引用类型的参数,则要使用Dynamic Delegates。 例如,以TArray的引用类型为例:
DECLARE_DYNAMIC_DELEGATE_OneParam(FMyDelegate, const TArray<FString>& MyArray);
APIs
AddDynamic
UE4提供了一个宏:AddDynamic,作用是省去编写FScriptDelegate
。
例如,原本要这么写:
FScriptDelegate DelegateBegin;
DelegateBegin.BindUFunction(PlayerController, "OnWeaponOverlapBegin");
GunMeshComp->OnComponentBeginOverlap.Add(DelegateBegin);
使用AddDynamic
可以这么写:
GunMeshComp->OnComponentBeginOverlap.AddDynamic(this, &ATestTDCharacter::OnWeaponOverlapBegin);
使用AddDynamic注册函数时,函数仍然需要添加UFUNCTION()。
AddLambda
If you don’t want to define callback function as member function of class, define callback function in where it be registered, you can use AddLambda
.
Example:
Engine\Source\Editor\SequenceRecorder\Private\SequenceRecorderModule.cpp
virtual void StartupModule() override
{
// register standalone UI
auto RegisterTabSpawner = []()
{
FGlobalTabmanager::Get()->RegisterNomadTabSpawner(SequenceRecorderTabName, FOnSpawnTab::CreateStatic(&FSequenceRecorderModule::SpawnSequenceRecorderTab))
.SetGroup(WorkspaceMenu::GetMenuStructure().GetLevelEditorCategory())
.SetDisplayName(LOCTEXT("SequenceRecorderTabTitle", "Sequence Recorder"))
.SetTooltipText(LOCTEXT("SequenceRecorderTooltipText", "Open the Sequence Recorder tab."))
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "SequenceRecorder.TabIcon"));
};
LevelEditorTabManagerChangedHandle = LevelEditorModule.OnTabManagerChanged().AddLambda(RegisterTabSpawner);
}
天上的神明和星辰,人间的艺术与真纯,我们所敬畏和景仰的,莫过于此。-丰子恺