天天看點

【UE4基礎】全面了解UE4委托

轉載自:全面了解UE4委托 - 可可西 - 部落格園UE4中的delegate(委托)常用于解耦不同對象之間的關聯:委托的觸發者不與監聽者有直接關聯,兩者通過委托對象間接地建立聯系 監聽者通過将響應函數綁定到委托上,使得委托觸發時立即收到通知,并進行相

【UE4基礎】全面了解UE4委托

https://www.cnblogs.com/kekec/p/10678905.html

總體

UE4中的delegate(委托)常用于解耦不同對象之間的關聯:委托的觸發者不與監聽者有直接關聯,兩者通過委托對象間接地建立聯系

監聽者通過将響應函數綁定到委托上,使得委托觸發時立即收到通知,并進行相關邏輯處理

委托,又稱代理,本質是一個特殊類的對象,它内部可以儲存(一個或多個)函數指針、調用參數和傳回值

委托的作用如同函數指針,但它更安全(支援編譯期類型檢查),而且更易于使用。

UE4在DelegateCombinations.h提供了一些宏來友善開發者快速來自定義一個delegate類型

大緻地使用流程如下:

① 使用DECLARE_*宏聲明一個自定義delegate類型FDelegateXXX

② 聲明一個FDelegateXXX類型的代理對象

③ 綁定需要執行的函數指針到代理對象上

④ 觸發代理對象中的函數指針會立即執行

⑤ 不需要某個函數指針時,可将其從代理對象中解綁

UE4提供了五類Delegate:

名稱

是否支援反射

以及序列化

能否有傳回值

是否支援

Payload參數

觸發代理 綁定個數 支援的綁定執行個體類型
單點傳播代理

DECLARE_DELEGATE_*

DECLARE_DELEGATE_RetVal_*

可以有  是

① 無傳回值情況

bool ExecuteIfBound(...)

void Execute(...)

② 有傳回值情況

RetValue Execute(...)

注:RetValue為綁定函數

      的傳回值

1個

① Static函數  // BindStatic

② 普通C++對象的成員函數  // BindRaw

③ Lambda表達式  // BindLambda

// BindWeakLambda

④ 與某個UObject對象關聯的Lambda表達式 

⑤ 共享引用包裹的普通C++對象的成員函數  // BindSP

// BindThreadSafeSP

⑥ 線程安全的共享引用包裹的普通C++對象的成員函數  

⑦ UObject對象的成員函數 // BindUObject

⑧ UObject對象的UFunction成員函數  // BindUFunction

多點傳播代理

(多點傳播代理)

DECLARE_MULTICAST_DELEGATE_*  是 void Broadcast(...) 多個

① Static函數  // AddStatic

② 普通C++對象的成員函數  // AddRaw

③ Lambda表達式  // AddLambda

// AddWeakLambda

④ 與某個UObject對象關聯的Lambda表達式  

⑤ 共享引用包裹的普通C++對象的成員函數  // AddSP

// AddThreadSafeSP

⑥ 線程安全的共享引用包裹的普通C++對象的成員函數 

⑦ UObject對象的成員函數  // AddUObject

⑧ UObject對象的UFunction成員函數 // AddUFunction

--------------------------------------

另外,可以建立FDelegate對象,然後調用Add函數

事件 DECLARE_EVENT_*  是 void Broadcast(...) 多個 同上
動态代理

DECLARE_DYNAMIC_DELEGATE_*

DECLARE_DYNAMIC_DELEGATE_RetVal_*

可以有 否 

① 無傳回值情況

bool ExecuteIfBound(...)

void Execute(...)

② 有傳回值情況

RetValue Execute(...)

注:RetValue為綁定函數

     的傳回值

1個

// BindUFunction

UObject對象的UFunction成員函數

--------------------------------------

另外,可以使用BindDynamic宏來綁定

動态多點傳播代理 DECLARE_DYNAMIC_MULTICAST_DELEGATE_*

藍圖中可使用

void Broadcast(...) 多個

// Add函數、AddDynamic宏

// AddUnique函數、AddUniqueDynamic宏

UObject對象的UFunction成員函數

 注1:Payload為代理綁定時傳遞的額外參數變量清單,這些參數會存儲在代理對象内部;在觸發代理時,Payload會緊跟着Execute、ExecuteInBound或Broadcast傳入的參數之後,填充到綁定函數指針的參數清單中,然後執行。

DECLARE_DELEGATE_OneParam(FTestDelegate, int);

static void StaticDelegateProc(int nCode)
{
    UE_LOG(LogTemp, Log, TEXT("StaticDelegateProc : %d"), nCode);
}

static void StaticDelegateProcTest(int nCode, float dis, FString txt)
{
    UE_LOG(LogTemp, Log, TEXT("StaticDelegateProcTest : %d %f %s"), nCode, dis, *txt);
}

FTestDelegate DelegateObj1;
DelegateObj1.BindStatic(StaticDelegateProc);
DelegateObj1.ExecuteIfBound(1);

// Payload示例
FTestDelegate DelegateObj2;
DelegateObj2.BindStatic(StaticDelegateProcTest, 12.0f, FString(TEXT("Hello")));  // 12.0f、FString(TEXT("Hello"))為綁定時傳入的Payload參數
DelegateObj2.ExecuteIfBound(2);

/******* 建立帶參數的Timer *******/
UCLASS()
class UDelegatepTimerTest : public UObject
{
    GENERATED_BODY()
public:
    void DelegateProc1(FString map)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("DelegateProc1 : %d"), nCode);
    }

    void Test()
    {
        FTimerHandle TimeHandle;
        FTimerDelegate MyDelegate;
        MyDelegate.BindUObject(this, &UDelegatepTimerTest::DelegateProc1, FString(TEXT("FarmLand")));
        GetWorld()->GetTimerManager().SetTimer(TimeHandle, MyDelegate, 5.0f, false); // 建立一個5.0s的一次性定時器  Payload示例
    }
};
           

注2:動态代理、動态多點傳播代理不支援Payload,是以,綁定函數與代理對象的參數、傳回值必須完全一緻。

下面為一些類型示例:

① 單點傳播代理

DECLARE_DELEGATE( FSimpleDelegate );  // 無參、無傳回值

DECLARE_DELEGATE_OneParam(FPakEncryptionKeyDelegate, uint8[32]);  // 1個參數、無傳回值

DECLARE_DELEGATE_TwoParams(FPakSigningKeysDelegate, TArray<uint8>&, TArray<uint8>&);  // 2個參數、無傳回值

DECLARE_DELEGATE_RetVal_ThreeParams(bool, FOnMountPak, const  FString&, int32, IPlatformFile::FDirectoryVisitor*);  // 3個參數、bool傳回值

② 多點傳播代理

DECLARE_MULTICAST_DELEGATE( FSimpleMulticastDelegate );  // 無參

DECLARE_MULTICAST_DELEGATE_TwoParams(FOnTreeStarted, const  UBehaviorTreeComponent&, const UBehaviorTree& );  // 2個參數

DECLARE_MULTICAST_DELEGATE_FourParams(FOnOpenURL, UIApplication*, NSURL*, NSString*, id); // 4個參數

③ 事件

DECLARE_EVENT(UWorld, FOnTickFlushEvent);  // 無參

DECLARE_EVENT_OneParam(IWebBrowserWindow, FOnTitleChanged, FString); // 1個參數

④ 動态代理

DECLARE_DYNAMIC_DELEGATE(FOnGameWindowCloseButtonClickedDelegate);  // 無參、無傳回值

DECLARE_DYNAMIC_DELEGATE_OneParam(FOnAssetLoaded, class UObject*, Loaded); // 1個參數、無傳回值

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( FLevelStreamingLoadedStatus );  // 無參

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLandedSignature, const FHitResult&, Hit);  // 1個參數

DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FMovementModeChangedSignature, class ACharacter*, Character, EMovementMode, PrevMovementMode, uint8, PreviousCustomMode);  // 3個參數
           

單點傳播代理

1. 定義代理類型

① 定義傳回值為void含1個int類型參數的單點傳播代理類型FCharacterDelegate

DECLARE_DELEGATE_OneParam(FCharacterDelegate, int); // TBaseDelegate<void, int>

【UE4基礎】全面了解UE4委托

② 定義傳回值為bool含1個int類型參數的單點傳播代理類型FCharacterDelegate_RetVal

DECLARE_DELEGATE_RetVal_OneParam(bool, FCharacterDelegate_RetVal, int);  // TBaseDelegate<bool, int>

【UE4基礎】全面了解UE4委托

2.  聲明代理對象

FCharacterDelegate CharacterDelegate;

FCharacterDelegate_RetVal CharacterDelegateRetVal;

以FCharacterDelegate為例,講述單點傳播代理的綁定、觸發執行及存在的風險

/*** TPSProjectCharacter.h ***/

UCLASS()
class UDelegatepTestClass : public UObject
{
    GENERATED_BODY()
protected:
    int m_nValue = 0;
public:
    void DelegateProc1(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("DelegateProc1 : %d"), nCode);
    }

    UFUNCTION() void DelegateUFunctionProc1(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("DelegateUFunctionProc1 : %d"), nCode);
    }
};

class DelegateCppTestClass
{
    int m_nValue = 0;
public:

    void CppDelegateProc(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("CppDelegateProc : %d"), nCode);
    }

    void CppDelegateProc2(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("CppDelegateProc2 : %d"), nCode);
    }

    void CppDelegateProc3(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("CppDelegateProc3 : %d"), nCode);
    }

    void CppDelegateProc4(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("CppDelegateProc4 : %d"), nCode);
    }

    void CppDelegateProc5(int nCode)
    {
        this->m_nValue = nCode;
        UE_LOG(LogTemp, Log, TEXT("CppDelegateProc5 : %d"), nCode);
    }
};

UCLASS(config=Game)
class ATPSProjectCharacter : public ACharacter
{
        GENERATED_BODY()

public:

    static void StaticCharacterDelegateProc(int nCode);  

    void OnBind();
    void OnExecute();
    void OnUnbind(); 

    FCharacterDelegate CharacterDelegate1;
    FCharacterDelegate CharacterDelegate2;
    FCharacterDelegate CharacterDelegate3;
    FCharacterDelegate CharacterDelegate4;
    FCharacterDelegate CharacterDelegate5;
    FCharacterDelegate CharacterDelegate6;
    FCharacterDelegate CharacterDelegate7;
    FCharacterDelegate CharacterDelegate8;
    FCharacterDelegate CharacterDelegate9;
    FCharacterDelegate CharacterDelegate10;
    FCharacterDelegate CharacterDelegate11;
    FCharacterDelegate CharacterDelegate12;
    FCharacterDelegate CharacterDelegate13; 
};


/*** TPSProjectCharacter.cpp ***/
static void StaticDelegateProc(int nCode)
{
    UE_LOG(LogTemp, Log, TEXT("StaticDelegateProc : %d"), nCode);
}

void ATPSProjectCharacter::StaticCharacterDelegateProc(int nCode)
{
    UE_LOG(LogTemp, Log, TEXT("StaticCharacterDelegateProc : %d"), nCode);
}

void ATPSProjectCharacter::OnBind()
{
    // Bind Static
    CharacterDelegate1.BindStatic(StaticDelegateProc);

    CharacterDelegate2.BindStatic(ATPSProjectCharacter::StaticCharacterDelegateProc);

    // Bind Raw
    DelegateCppTestClass Obj1;
    CharacterDelegate3.BindRaw(&Obj1, &DelegateCppTestClass::CppDelegateProc);

    // Bind Lambda
    auto LambdaDelegateProc = [](int nCode)->void
    {
        UE_LOG(LogTemp, Log, TEXT("LambdaDelegateProc : %d"), nCode);
    };
    CharacterDelegate4.BindLambda(LambdaDelegateProc);

    CharacterDelegate5.BindLambda(
        [](int nCode)->void
        {
            UE_LOG(LogTemp, Log, TEXT("LambdaDelegateProc2 : %d"), nCode);
        }
    );

    // Bind Weak Lambda
    auto WeakLambdaDelegateProc = [](int nCode)->void
    {
        UE_LOG(LogTemp, Log, TEXT("WeakLambdaDelegateProc : %d"), nCode);
    };
    UDelegatepTestClass* UObj1 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegate6.BindWeakLambda(UObj1, WeakLambdaDelegateProc);

    UDelegatepTestClass* UObj2 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegate7.BindWeakLambda(
        UObj2, [](int nCode)->void
        {
            UE_LOG(LogTemp, Log, TEXT("WeakLambdaDelegateProc2 : %d"), nCode);
        }
    );

    // Bind SP(Shared Pointer)
    TSharedRef<DelegateCppTestClass> ObjSP1 = MakeShareable(new DelegateCppTestClass());
    CharacterDelegate8.BindSP(ObjSP1, &DelegateCppTestClass::CppDelegateProc2);

    TSharedRef<DelegateCppTestClass> ObjSP2 = MakeShared<DelegateCppTestClass>();
    CharacterDelegate9.BindSP(ObjSP2, &DelegateCppTestClass::CppDelegateProc3);

    // Bind Thread Safe SP(Shared Pointer)
    TSharedRef<DelegateCppTestClass, ESPMode::ThreadSafe> ObjSafeSP1 = MakeShareable(new DelegateCppTestClass());
    CharacterDelegate10.BindThreadSafeSP(ObjSafeSP1, &DelegateCppTestClass::CppDelegateProc4);

    TSharedRef<DelegateCppTestClass, ESPMode::ThreadSafe> ObjSafeSP2 = MakeShared<DelegateCppTestClass, ESPMode::ThreadSafe>();
    CharacterDelegate11.BindThreadSafeSP(ObjSafeSP2, &DelegateCppTestClass::CppDelegateProc5);

    // Bind UObject
    UDelegatepTestClass* UObj3 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegate12.BindUObject(UObj3, &UDelegatepTestClass::DelegateProc1);

    // Bind UFunction
    UDelegatepTestClass* UObj4 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegate13.BindUFunction(UObj4, STATIC_FUNCTION_FNAME(TEXT("UDelegatepTestClass::DelegateUFunctionProc1")));

}

void ATPSProjectCharacter::OnExecute()
{
    CharacterDelegate1.ExecuteIfBound(1);
    CharacterDelegate2.ExecuteIfBound(2);
    CharacterDelegate3.ExecuteIfBound(3);
    CharacterDelegate4.ExecuteIfBound(4);
    CharacterDelegate5.ExecuteIfBound(5);
    CharacterDelegate6.ExecuteIfBound(6);
    CharacterDelegate7.ExecuteIfBound(7);
    CharacterDelegate8.ExecuteIfBound(8);
    CharacterDelegate9.ExecuteIfBound(9);
    CharacterDelegate10.ExecuteIfBound(10);
    CharacterDelegate11.ExecuteIfBound(11);
    CharacterDelegate12.ExecuteIfBound(12);
    if (CharacterDelegate13.IsBound())
    {
        CharacterDelegate13.Execute(13);
    }
}

void ATPSProjectCharacter::OnUnbind()
{
    CharacterDelegate1.Unbind();
    CharacterDelegate2.Unbind();
    CharacterDelegate3.Unbind();
    CharacterDelegate4.Unbind();
    CharacterDelegate5.Unbind();
    CharacterDelegate6.Unbind();
    CharacterDelegate7.Unbind();
    CharacterDelegate8.Unbind();
    CharacterDelegate9.Unbind();
    CharacterDelegate10.Unbind();
    CharacterDelegate11.Unbind();
    CharacterDelegate12.Unbind();
    CharacterDelegate13.Unbind();
}
           

注1:BindRaw函數用于綁定普通c++對象的成員函數,若該c++對象已被銷毀,觸發代理執行該對象的成員函數,将會導緻記憶體違規操作

注2:BindLambda函數用于綁定lambda表達式,若lambda表達式捕獲外部變量已被銷毀,觸發代理執行lambda表達式,将會導緻記憶體違規操作

注3:BindWeakLambda、BindUObject、BindUFunction綁定時會與一個UObject對象進行弱引用關聯(不影響該對象被gc回收)

         若UObject對象被gc回收,直接調用Execute觸發代理,将會導緻記憶體違規操作;可先調用IsBound或調用ExecuteIfBound觸發代理來檢查該UObject的有效性,再來執行代理

注4:BindSP、BindThreadSafeSP綁定時會與一個智能指針對象進行弱引用關聯(不影響該對象的記憶體回收)

         若智能指針對象的記憶體被回收,直接調用Execute觸發代理,将會導緻記憶體違規操作;可先調用IsBound或調用ExecuteIfBound觸發代理來檢查該智能指針對象的有效性,再來執行代理

注5:單點傳播代理對象在被銷毀時,會在其析構函數中調用Unbind進行解綁操作

注6:不同的綁定執行個體類型定義在:DelegateInstancesImpl.h

BindStatic(綁定執行個體類型為:TBaseStaticDelegateInstance)

【UE4基礎】全面了解UE4委托

BindRaw(綁定執行個體類型為:TBaseRawMethodDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

BindLambda(綁定執行個體類型為:TBaseFunctorDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

 BindWeakLambda(綁定執行個體類型為:TWeakBaseFunctorDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

 BindSP(綁定執行個體類型為:TBaseSPMethodDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

BindThreadSafeSP(綁定執行個體類型為:TBaseSPMethodDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

 BindUObject(綁定執行個體類型為:TBaseUObjectMethodDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

 BindUFunction(綁定執行個體類型為:TBaseUFunctionDelegateInstance)

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

多點傳播代理(多點傳播代理)

1. 定義傳回值為void含1個int類型參數的多點傳播代理類型FCharacterDelegate_Multicase

DECLARE_MULTICAST_DELEGATE_OneParam(FCharacterDelegate_Multicast, int);  // TMulticastDelegate<void, int>

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

2.  聲明代理對象

FCharacterDelegate_Multicast CharacterDelegateMulticast1;

以FCharacterDelegate_Multicast為例,講述多點傳播代理的綁定、觸發執行及存在的風險

void ATPSProjectCharacter::OnDelegateMulticastTest()
{
    // Add Static
    bool b1 = CharacterDelegateMulticast1.IsBound(); // false
    
    FDelegateHandle HandleMC1 = CharacterDelegateMulticast1.AddStatic(StaticDelegateProc); // 綁定執行個體個數為:1
    CharacterDelegateMulticast1.AddStatic(ATPSProjectCharacter::StaticCharacterDelegateProc); // 綁定執行個體個數為:2

    bool b2 = CharacterDelegateMulticast1.IsBound(); // true
    bool b3 = CharacterDelegateMulticast1.IsBoundToObject(this); // false

    CharacterDelegateMulticast1.Remove(HandleMC1); // 綁定執行個體個數為:1

    FCharacterDelegate_Multicast::FDelegate MC1 = FCharacterDelegate_Multicast::FDelegate::CreateStatic(StaticDelegate2Proc);
    CharacterDelegateMulticast1.Add(MC1); // 綁定執行個體個數為:2
    CharacterDelegateMulticast1.Broadcast(100); // 執行綁定執行個體清單(共2個)  注:執行順序可能與函數的添加順序不相同
    

    // Add Raw
    DelegateCppTestClass ObjMC1;
    CharacterDelegateMulticast2.AddRaw(&ObjMC1, &DelegateCppTestClass::CppDelegateProc); // 綁定執行個體個數為:1
    CharacterDelegateMulticast2.AddRaw(&ObjMC1, &DelegateCppTestClass::CppDelegateProc2); // 綁定執行個體個數為:2
    CharacterDelegateMulticast2.AddStatic(ATPSProjectCharacter::StaticCharacterDelegateProc); // 綁定執行個體個數為:3

    bool b4 = CharacterDelegateMulticast2.IsBoundToObject(&ObjMC1); // true

    CharacterDelegateMulticast2.RemoveAll(&ObjMC1); // CppDelegateProc、CppDelegateProc2被删除,綁定執行個體個數為:1

    bool b5 = CharacterDelegateMulticast2.IsBoundToObject(&ObjMC1); // false

    CharacterDelegateMulticast2.Broadcast(101); // 執行綁定執行個體清單(共1個)  注:執行順序可能與函數的添加順序不相同
    
    CharacterDelegateMulticast2.Clear(); // 綁定執行個體個數為:0

    // Add Lambda
    auto LambdaDelegateMCProc = [](int nCode)->void
    {
        UE_LOG(LogTemp, Log, TEXT("LambdaDelegateMCProc : %d"), nCode);
    };
    CharacterDelegateMulticast3.AddLambda(LambdaDelegateMCProc);// 綁定執行個體個數為:1

    CharacterDelegateMulticast3.AddLambda(
        [](int nCode)->void
    {
        UE_LOG(LogTemp, Log, TEXT("LambdaDelegateMCProc2 : %d"), nCode);
    }
    );// 綁定執行個體個數為:2
    CharacterDelegateMulticast3.Broadcast(102);// 執行綁定執行個體清單(共2個)  注:執行順序可能與函數的添加順序不相同

    // Add Weak Lambda
    auto WeakLambdaDelegateMCProc = [](int nCode)->void
    {
        UE_LOG(LogTemp, Log, TEXT("WeakLambdaDelegateMCProc : %d"), nCode);
    };
    UDelegatepTestClass* UObjMC1 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegateMulticast4.AddWeakLambda(UObjMC1, WeakLambdaDelegateMCProc);// 綁定執行個體個數為:1

    UDelegatepTestClass* UObjMC2 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegateMulticast4.AddWeakLambda(
        UObjMC2, [](int nCode)->void
    {
        UE_LOG(LogTemp, Log, TEXT("WeakLambdaDelegateMCProc2 : %d"), nCode);
    }
    );// 綁定執行個體個數為:2
    CharacterDelegateMulticast4.Broadcast(103);// 執行綁定執行個體清單(共2個)  注:執行順序可能與函數的添加順序不相同

    // Add SP(Shared Pointer)
    TSharedRef<DelegateCppTestClass> ObjMCSP1 = MakeShareable(new DelegateCppTestClass());
    CharacterDelegateMulticast5.AddSP(ObjMCSP1, &DelegateCppTestClass::CppDelegateProc2);// 綁定執行個體個數為:1

    TSharedRef<DelegateCppTestClass> ObjMCSP2 = MakeShared<DelegateCppTestClass>();
    CharacterDelegateMulticast5.AddSP(ObjMCSP2, &DelegateCppTestClass::CppDelegateProc3);// 綁定執行個體個數為:2
    CharacterDelegateMulticast5.Broadcast(104);

    // Add Thread Safe SP(Shared Pointer)
    TSharedRef<DelegateCppTestClass, ESPMode::ThreadSafe> ObjSafeMCSP1 = MakeShareable(new DelegateCppTestClass());
    CharacterDelegateMulticast6.AddThreadSafeSP(ObjSafeMCSP1, &DelegateCppTestClass::CppDelegateProc4);// 綁定執行個體個數為:1

    TSharedRef<DelegateCppTestClass, ESPMode::ThreadSafe> ObjSafeMCSP2 = MakeShared<DelegateCppTestClass, ESPMode::ThreadSafe>();
    CharacterDelegateMulticast6.AddThreadSafeSP(ObjSafeMCSP2, &DelegateCppTestClass::CppDelegateProc5);// 綁定執行個體個數為:2

    CharacterDelegateMulticast6.Broadcast(105);// 執行綁定執行個體清單(共2個)  注:執行順序可能與函數的添加順序不相同

    // Add UObject
    UDelegatepTestClass* UObjMC3 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegateMulticast7.AddUObject(UObjMC3, &UDelegatepTestClass::DelegateProc1);// 綁定執行個體個數為:1
    CharacterDelegateMulticast7.AddUObject(UObjMC3, &UDelegatepTestClass::DelegateProc2);// 綁定執行個體個數為:2

    CharacterDelegateMulticast7.Broadcast(106);// 執行綁定執行個體清單(共2個)  注:執行順序可能與函數的添加順序不相同

    // Add UFunction
    UDelegatepTestClass* UObjMC4 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegateMulticast8.AddUFunction(UObjMC4, STATIC_FUNCTION_FNAME(TEXT("UDelegatepTestClass::DelegateUFunctionProc1")));// 綁定執行個體個數為:1
    CharacterDelegateMulticast8.Broadcast(107);// 執行綁定執行個體清單(共1個)  注:執行順序可能與函數的添加順序不相同
}
           

注1:AddRaw函數用于綁定普通c++對象的成員函數,若該c++對象已被銷毀,觸發代理執行該對象的成員函數,将會導緻記憶體違規操作

注2:AddLambda函數用于綁定lambda表達式,若lambda表達式捕獲外部變量已被銷毀,觸發代理執行lambda表達式,将會導緻記憶體違規操作

注3:AddWeakLambda、AddUObject、AddUFunction綁定時會與一個UObject對象進行弱引用關聯(不影響該對象被gc回收),在觸發代理時,會先檢查該UObject的有效性,再來執行代理

注4:BindSP、BindThreadSafeSP綁定時會與一個智能指針對象進行弱引用關聯(不影響該對象的記憶體回收),在觸發代理時,會先檢查該智能指針對象的有效性,再來執行代理

注5:可通過Remove删除指定Handle的代理對象;通過RemoveAll删除相關UObject對象所有的代理對象;通過Clear清除代理對象清單

事件

1. 定義傳回值為void含1個int類型參數的事件類型FCharacterEvent

DECLARE_EVENT_OneParam(ATPSProjectCharacter, FCharacterEvent, int);  // TBaseMulticastDelegate<void, int>

【UE4基礎】全面了解UE4委托

注1:定義事件類型宏的第一個參數為擁有該事件類型A的類型B,即為類型B為事件類型A的友元類,可以通路A中的私有成員

注2:定義事件類型宏一般放在一個類的内部(即通路該類型時需要帶上所在類的名稱字首,如ATPSProjectCharacter::FCharacterEvent),可有效減少事件類型名稱沖突

2.  聲明代理對象

FCharacterEvent CharacterEvent;

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

事件本質是一個多點傳播代理,另外,在事件的友元類型ATPSProjectCharacter中,可通路事件的私有成員

動态代理

1. 定義傳回值為void含1個int類型參數的動态代理類型FCharacterDelegate_Dynamic

DECLARE_DYNAMIC_DELEGATE_OneParam(FCharacterDelegate_Dynamic, int, nCode); // TBaseDynamicDelegate<FWeakObjectPtr, void, int> 

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

2. 定義傳回值為bool含1個int類型參數的動态代理類型FCharacterDelegate_DynamicRetVal

DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(bool, FCharacterDelegate_DynamicRetVal, int, nCode);  // TBaseDynamicDelegate<FWeakObjectPtr, bool, int> 

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

以FCharacterDelegate_Dynamic為例,講述動态代理的綁定、觸發執行及存在的風險

void ATPSProjectCharacter::OnDelegateDynamicTest()
{
    bool bd1 = CharacterDelegateDynamic.IsBound(); // false

    UDelegatepTestClass* UObjDy1 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    CharacterDelegateDynamic.BindUFunction(UObjDy1, STATIC_FUNCTION_FNAME(TEXT("UDelegatepTestClass::DelegateUFunctionProc1")));// 綁定執行個體個數為:1

    bool bd2 = CharacterDelegateDynamic.IsBound(); // true

    CharacterDelegateDynamic.ExecuteIfBound(200);

    CharacterDelegateDynamic.Unbind();

    // 使用BindDynamic宏
    CharacterDelegateDynamic2.BindDynamic(this, &ATPSProjectCharacter::DynamicMulticastProc);
    if (CharacterDelegateDynamic2.IsBound()) // true
    {
        CharacterDelegateDynamic2.Execute(201);
    }    

    CharacterDelegateDynamic2.Clear(); // 功能與Unbind一樣,内部是直接調用Unbind方法
}
           

注:BindUFunction綁定時會與一個UObject對象進行弱引用關聯(不影響該對象被gc回收)

      若UObject對象被gc回收,直接調用Execute觸發代理,将會導緻記憶體違規操作;可先調用IsBound或調用ExecuteIfBound觸發代理來檢查該UObject的有效性,再來執行代理

動态多點傳播代理

定義傳回值為void含1個int類型參數的動态多點傳播代理類型FCharacterDelegate_DynamicMulticast

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCharacterDelegate_DynamicMulticast, int, nCode); // TBaseDynamicMulticastDelegate<FWeakObjectPtr, void, int>

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

 FCharacterDelegate_DynamicMulticast為例,講述動态多點傳播代理的綁定、觸發執行及存在的風險 

void ATPSProjectCharacter::OnDelegateDynamicMulticastTest()
{
    UDelegatepTestClass* UObjDMC1 = NewObject<UDelegatepTestClass>(this, UDelegatepTestClass::StaticClass());
    // 使用AddDynamic宏
    //CharacterDelegateDynamicMulticast.AddDynamic(UObjDMC1, &UDelegatepTestClass::DelegateProc1); // 運作時錯誤:Unable to bind delegate (function might not be marked as a UFUNCTION or object may be pending kill)
    CharacterDelegateDynamicMulticast.AddDynamic(UObjDMC1, &UDelegatepTestClass::DelegateUFunctionProc1); // 綁定執行個體個數為:1
    //CharacterDelegateDynamicMulticast.AddDynamic(UObjDMC1, &UDelegatepTestClass::DelegateUFunctionProc1); // 運作時錯誤 加入DelegateUFunctionProc1的綁定執行個體已存在
    CharacterDelegateDynamicMulticast.AddDynamic(UObjDMC1, &UDelegatepTestClass::DelegateUFunctionProc2); // 綁定執行個體個數為:2

    // 使用AddUniqueDynamic宏
    CharacterDelegateDynamicMulticast.AddUniqueDynamic(this, &ATPSProjectCharacter::DynamicMulticastProc); // 綁定執行個體個數為:3
    CharacterDelegateDynamicMulticast.AddUniqueDynamic(this, &ATPSProjectCharacter::DynamicMulticastProc); // 加入DynamicMulticastProc的綁定執行個體已存在
    CharacterDelegateDynamicMulticast.AddUniqueDynamic(this, &ATPSProjectCharacter::DynamicMulticastProc2); // 綁定執行個體個數為:4
 
    FScriptDelegate delegateVar1; // FScriptDelegate即為TScriptDelegate<>
    delegateVar1.BindUFunction(this, STATIC_FUNCTION_FNAME(TEXT("ATPSProjectCharacter::DynamicMulticastProc3")));
    CharacterDelegateDynamicMulticast.Add(delegateVar1); // 綁定執行個體個數為:5
    FScriptDelegate delegateVar2;
    delegateVar2.BindUFunction(this, STATIC_FUNCTION_FNAME(TEXT("ATPSProjectCharacter::DynamicMulticastProc3")));
    //CharacterDelegateDynamicMulticast.Add(delegateVar2); // 運作時錯誤 加入DynamicMulticastProc3的綁定執行個體已存在
    CharacterDelegateDynamicMulticast.AddUnique(delegateVar2); // 加入DynamicMulticastProc3的綁定執行個體已存在

    // 使用RemoveDynamic宏
    CharacterDelegateDynamicMulticast.RemoveDynamic(this, &ATPSProjectCharacter::DynamicMulticastProc2); // 綁定執行個體個數為:4

    // 使用IsAlreadyBound宏
    bool bDMC1 = CharacterDelegateDynamicMulticast.IsAlreadyBound(this, &ATPSProjectCharacter::DynamicMulticastProc3);// true

    CharacterDelegateDynamicMulticast.Remove(delegateVar2); // 綁定執行個體個數為:3
    CharacterDelegateDynamicMulticast.Remove(UObjDMC1, STATIC_FUNCTION_FNAME(TEXT("UDelegatepTestClass::DelegateUFunctionProc1")));// 綁定執行個體個數為:2

    bool bDMC2 = CharacterDelegateDynamicMulticast.IsAlreadyBound(this, &ATPSProjectCharacter::DynamicMulticastProc3); // false

    CharacterDelegateDynamicMulticast.RemoveAll(this); // 綁定執行個體個數為:1

    CharacterDelegateDynamicMulticast.Broadcast(300); // 執行綁定執行個體清單(共1個)  注:執行順序可能與函數的添加順序不相同

    CharacterDelegateDynamicMulticast.Clear(); // 清除所有綁定執行個體
}
           

需要注意的是,隻有動态多點傳播代理才能在藍圖中使用(對其進行綁定、解綁、Broadcast、以及清除操作)

【UE4基礎】全面了解UE4委托

BP_MyTPSProjectCharacter是一個放置在關卡中的派生于ATPSProjectCharacter的藍圖對象

【UE4基礎】全面了解UE4委托

下圖為在關卡藍圖中配置設定并綁定事件到BP_MyTPSProjectCharacter執行個體的CharacterDelegateDynamicMulticast動态多點傳播代理變量上,按下8按鍵觸發代理執行

【UE4基礎】全面了解UE4委托
【UE4基礎】全面了解UE4委托

引擎内建委托 

系統和引擎

///
/* Engine\Source\Runtime\Core\Public\Misc\CoreDelegates.h **/
class CORE_API FCoreDelegates 
{
    // Callback for platform handling when flushing async loads.
    DECLARE_MULTICAST_DELEGATE(FOnAsyncLoadingFlush);
    static FOnAsyncLoadingFlush OnAsyncLoadingFlush;

    // Callback for a game thread interruption point when a async load flushing. Used to updating UI during long loads.
    DECLARE_MULTICAST_DELEGATE(FOnAsyncLoadingFlushUpdate);
    static FOnAsyncLoadingFlushUpdate OnAsyncLoadingFlushUpdate;

    // Callback on the game thread when an async load is started. This goes off before the packages has finished loading
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnAsyncLoadPackage, const FString&);
    static FOnAsyncLoadPackage OnAsyncLoadPackage;

    DECLARE_MULTICAST_DELEGATE_OneParam(FOnSyncLoadPackage, const FString&);
    static FOnSyncLoadPackage OnSyncLoadPackage;
    
    
    
    // Callback when an ensure has occurred
    static FOnHandleSystemEnsure OnHandleSystemEnsure;

    // Callback when an error (crash) has occurred
    static FOnHandleSystemError OnHandleSystemError;
    
    
    // Called when an error occurred.
    static FSimpleMulticastDelegate OnShutdownAfterError;

    // Called when appInit is called, very early in startup
    static FSimpleMulticastDelegate OnInit;

    // Called at the end of UEngine::Init, right before loading PostEngineInit modules for both normal execution and commandlets
    static FSimpleMulticastDelegate OnPostEngineInit;

    // Called at the very end of engine initialization, right before the engine starts ticking. This is not called for commandlets
    static FSimpleMulticastDelegate OnFEngineLoopInitComplete;

    // Called when the application is about to exit.
    static FSimpleMulticastDelegate OnExit;

    // Called when before the application is exiting.
    static FSimpleMulticastDelegate OnPreExit;
    
    
    // Called at the beginning of a frame
    static FSimpleMulticastDelegate OnBeginFrame;

    // Called at the end of a frame
    static FSimpleMulticastDelegate OnEndFrame;

    // Called at the beginning of a frame on the renderthread
    static FSimpleMulticastDelegate OnBeginFrameRT;

    // Called at the end of a frame on the renderthread
    static FSimpleMulticastDelegate OnEndFrameRT;
    
    
    // IOS-style temperature updates, allowing game to scale down to let temp drop (to avoid thermal throttling on mobile, for instance) */
    // There is a parellel enum in ApplicationLifecycleComponent
    enum class ETemperatureSeverity : uint8
    {
        Unknown,
        Good,
        Bad,
        Serious,
        Critical,

        NumSeverities,
    };
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnTemperatureChange, ETemperatureSeverity);
    static FOnTemperatureChange OnTemperatureChange;

    /** Called when the OS goes into low power mode */
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnLowPowerMode, bool);
    static FOnLowPowerMode OnLowPowerMode;
    
    
    DECLARE_MULTICAST_DELEGATE_TwoParams(FOnSystemResolutionChanged, uint32 /*ResX*/, uint32 /*ResY*/);
    static FOnSystemResolutionChanged OnSystemResolutionChanged;
    
    
    /** IOS-style application lifecycle delegates */
    DECLARE_MULTICAST_DELEGATE(FApplicationLifetimeDelegate);

    // This is called when the application is about to be deactivated (e.g., due to a phone call or SMS or the sleep button).
    // The game should be paused if possible, etc...
    static FApplicationLifetimeDelegate ApplicationWillDeactivateDelegate;
    
    // Called when the application has been reactivated (reverse any processing done in the Deactivate delegate)
    static FApplicationLifetimeDelegate ApplicationHasReactivatedDelegate;

    // This is called when the application is being backgrounded (e.g., due to switching
    // to another app or closing it via the home button)
    // The game should release shared resources, save state, etc..., since it can be
    // terminated from the background state without any further warning.
    static FApplicationLifetimeDelegate ApplicationWillEnterBackgroundDelegate; // for instance, hitting the home button
    
    // Called when the application is returning to the foreground (reverse any processing done in the EnterBackground delegate)
    static FApplicationLifetimeDelegate ApplicationHasEnteredForegroundDelegate;

    // This *may* be called when the application is getting terminated by the OS.
    // There is no guarantee that this will ever be called on a mobile device,
    // save state when ApplicationWillEnterBackgroundDelegate is called instead.
    static FApplicationLifetimeDelegate ApplicationWillTerminateDelegate;
    
    
    // Called when the OS needs control of the music (parameter is true) or when the OS returns
    // control of the music to the application (parameter is false). This can happen due to a
    // phone call or timer or other OS-level event. This is currently triggered only on iOS
    // devices.
    DECLARE_MULTICAST_DELEGATE_OneParam(FUserMusicInterruptDelegate, bool);
    static FUserMusicInterruptDelegate UserMusicInterruptDelegate;
    
    // [iOS only] Called when the mute switch is detected as changed or when the
    // volume changes. Parameter 1 is the mute switch state (true is muted, false is
    // unmuted). Parameter 2 is the volume as an integer from 0 to 100.
    DECLARE_MULTICAST_DELEGATE_TwoParams(FAudioMuteDelegate, bool, int);
    static FAudioMuteDelegate AudioMuteDelegate;
    
    // [iOS only] Called when the audio device changes
    // For instance, when the headphones are plugged in or removed
    DECLARE_MULTICAST_DELEGATE_OneParam(FAudioRouteChangedDelegate, bool);
    static FAudioRouteChangedDelegate AudioRouteChangedDelegate;
    
    
    // Called when the OS is running low on resources and asks the application to free up any cached resources, drop graphics quality etc.
    static FApplicationLifetimeDelegate ApplicationShouldUnloadResourcesDelegate;
    
    /** Sent when a device screen orientation changes */
    DECLARE_MULTICAST_DELEGATE_OneParam(FApplicationReceivedOnScreenOrientationChangedNotificationDelegate, int32);
    static FApplicationReceivedOnScreenOrientationChangedNotificationDelegate ApplicationReceivedScreenOrientationChangedNotificationDelegate;
    
    /** Callback for notifications regarding changes of the rendering thread. */
    DECLARE_MULTICAST_DELEGATE(FRenderingThreadChanged)

    /** Sent just after the rendering thread has been created. */
    static FRenderingThreadChanged PostRenderingThreadCreated;
    /* Sent just before the rendering thread is destroyed. */
    static FRenderingThreadChanged PreRenderingThreadDestroyed;
    
    
    // Called to request that systems free whatever memory they are able to. Called early in LoadMap.
    // Caller is responsible for flushing rendering etc. See UEngine::TrimMemory
    static FSimpleMulticastDelegate& GetMemoryTrimDelegate();

    // Called when OOM event occurs, after backup memory has been freed, so there's some hope of being effective
    static FSimpleMulticastDelegate& GetOutOfMemoryDelegate();
};

///
/* Engine\Source\Runtime\CoreUObject\Public\UObject\UObjectGlobals.h **/
struct COREUOBJECT_API FCoreUObjectDelegates
{
    /** Sent at the very beginning of LoadMap */
    DECLARE_MULTICAST_DELEGATE_OneParam(FPreLoadMapDelegate, const FString& /* MapName */);
    static FPreLoadMapDelegate PreLoadMap;

    /** Sent at the _successful_ end of LoadMap */
    DECLARE_MULTICAST_DELEGATE_OneParam(FPostLoadMapDelegate, UWorld* /* LoadedWorld */);
    static FPostLoadMapDelegate PostLoadMapWithWorld;
    
    /** Sent when a network replay has started */
    static FSimpleMulticastDelegate PostDemoPlay;

    /** Called before garbage collection */
    static FSimpleMulticastDelegate& GetPreGarbageCollectDelegate();

    /** Delegate type for reachability analysis external roots callback. First parameter is FGarbageCollectionTracer to use for tracing, second is flags with which objects should be kept alive regardless, third is whether to force single threading */
    DECLARE_MULTICAST_DELEGATE_ThreeParams(FTraceExternalRootsForReachabilityAnalysisDelegate, FGarbageCollectionTracer&, EObjectFlags, bool);

    /** Called as last phase of reachability analysis. Allow external systems to add UObject roots *after* first reachability pass has been done */
    static FTraceExternalRootsForReachabilityAnalysisDelegate TraceExternalRootsForReachabilityAnalysis;

    /** Called after reachability analysis, before any purging */
    static FSimpleMulticastDelegate PostReachabilityAnalysis;

    /** Called after garbage collection */
    static FSimpleMulticastDelegate& GetPostGarbageCollect();

    /** Called before ConditionalBeginDestroy phase of garbage collection */
    static FSimpleMulticastDelegate PreGarbageCollectConditionalBeginDestroy;

    /** Called after ConditionalBeginDestroy phase of garbage collection */
    static FSimpleMulticastDelegate PostGarbageCollectConditionalBeginDestroy;

    /** Queries whether an object should be loaded on top ( replace ) an already existing one */
    DECLARE_DELEGATE_RetVal_OneParam(bool, FOnLoadObjectsOnTop, const FString&);
    static FOnLoadObjectsOnTop ShouldLoadOnTop;

    /** Called when path to world root is changed */
    DECLARE_MULTICAST_DELEGATE_OneParam(FPackageCreatedForLoad, class UPackage*);
    static FPackageCreatedForLoad PackageCreatedForLoad;
};

///
/* Engine\Source\Runtime\Engine\Classes\Engine\Engine.h **/
class ENGINE_API UEngine : public UObject , public FExec 
{
    /** Delegate called just prior to rendering. */
    FPreRenderDelegate PreRenderDelegate;
    FPreRenderDelegate& GetPreRenderDelegate() { return PreRenderDelegate; }

    /** 
     * Error message event relating to server travel failures 
     * 
     * @param Type type of travel failure
     * @param ErrorString additional error message
     */
    DECLARE_EVENT_ThreeParams(UEngine, FOnTravelFailure, UWorld*, ETravelFailure::Type, const FString&);
    FOnTravelFailure TravelFailureEvent;

    /** 
     * Error message event relating to network failures 
     * 
     * @param Type type of network failure
     * @param Name name of netdriver that generated the failure
     * @param ErrorString additional error message
     */
    DECLARE_EVENT_FourParams(UEngine, FOnNetworkFailure, UWorld*, UNetDriver*, ENetworkFailure::Type, const FString&);
    FOnNetworkFailure NetworkFailureEvent;

    /** 
     * Network lag detected. For the server this means all clients are timing out. On the client it means you are timing out.
     */
    DECLARE_EVENT_ThreeParams(UEngine, FOnNetworkLagStateChanged, UWorld*, UNetDriver*, ENetworkLagState::Type);
    FOnNetworkLagStateChanged NetworkLagStateChangedEvent;
    
    
    /** Triggered when a world is added. */    
    DECLARE_EVENT_OneParam( UEngine, FWorldAddedEvent , UWorld* );
    
    /** Return the world added event. */
    FWorldAddedEvent&        OnWorldAdded() { return WorldAddedEvent; }
    
    /** Triggered when a world is destroyed. */    
    DECLARE_EVENT_OneParam( UEngine, FWorldDestroyedEvent , UWorld* );
    
    /** Return the world destroyed event. */    
    FWorldDestroyedEvent&    OnWorldDestroyed() { return WorldDestroyedEvent; }
};
           

編輯器

///
/* Engine\Source\Editor\UnrealEd\Public\Editor.h **/
#if WITH_EDITOR
struct UNREALED_API FEditorDelegates
{
    /** Sent when a PIE session is beginning (before we decide if PIE can run - allows clients to avoid blocking PIE) */
    static FOnPIEEvent PreBeginPIE;
    /** Sent when a PIE session is beginning (but hasn't actually started yet) */
    static FOnPIEEvent BeginPIE;
    /** Sent when a PIE session has fully started and after BeginPlay() has been called */
    static FOnPIEEvent PostPIEStarted;
    /** Sent when a PIE session is ending, before anything else happens */
    static FOnPIEEvent PrePIEEnded;
    /** Sent when a PIE session is ending */
    static FOnPIEEvent EndPIE;
    
    /** Called when a map is opened, giving map name, and whether it was a template */
    static FOnMapOpened OnMapOpened;
};
#endif
           

遊戲世界

///
/* Engine\Source\Runtime\Engine\Classes\Engine\World.h **/
class ENGINE_API FWorldDelegates
{
    DECLARE_MULTICAST_DELEGATE_TwoParams(FOnWorldTickStart, ELevelTick, float);
    static FOnWorldTickStart OnWorldTickStart;
    
    // Delegate called before actors are ticked for each world. Delta seconds is already dilated and clamped.
    DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnWorldPreActorTick, UWorld* /*World*/, ELevelTick/**Tick Type*/, float/**Delta Seconds*/);
    static FOnWorldPreActorTick OnWorldPreActorTick;

    DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnWorldPostActorTick, UWorld* /*World*/, ELevelTick/**Tick Type*/, float/**Delta Seconds*/);
    static FOnWorldPostActorTick OnWorldPostActorTick;

    // Callback for world creation
    static FWorldEvent OnPostWorldCreation;
    
    // Callback for world initialization (pre)
    static FWorldInitializationEvent OnPreWorldInitialization;
    
    // Callback for world initialization (post)
    static FWorldInitializationEvent OnPostWorldInitialization;
    
    // Callback for world cleanup start
    static FWorldCleanupEvent OnWorldCleanup;

    // Callback for world cleanup end
    static FWorldCleanupEvent OnPostWorldCleanup;

    // Callback for world destruction (only called for initialized worlds)
    static FWorldEvent OnPreWorldFinishDestroy;

    // Sent when a ULevel is added to the world via UWorld::AddToWorld
    static FOnLevelChanged            LevelAddedToWorld;

    // Sent when a ULevel is removed from the world via UWorld::RemoveFromWorld or 
    // LoadMap (a NULL object means the LoadMap case, because all levels will be 
    // removed from the world without a RemoveFromWorld call for each)
    static FOnLevelChanged            LevelRemovedFromWorld;
    
    // Global Callback after actors have been initialized (on any world)
    static UWorld::FOnWorldInitializedActors OnWorldInitializedActors;
};

///
/* Engine\Source\Runtime\Engine\Classes\Engine\World.h **/
DECLARE_MULTICAST_DELEGATE_OneParam(FOnActorSpawned, AActor*);

class ENGINE_API UWorld final : public UObject, public FNetworkNotify 
{
    /** a delegate that broadcasts a notification whenever an actor is spawned */
    FOnActorSpawned OnActorSpawned;
    
    /** Add a listener for OnActorSpawned events */
    FDelegateHandle AddOnActorSpawnedHandler( const FOnActorSpawned::FDelegate& InHandler );

    /** Remove a listener for OnActorSpawned events */
    void RemoveOnActorSpawnedHandler( FDelegateHandle InHandle );
    
    
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnWorldInitializedActors, const FActorsInitializedParams&);
    FOnWorldInitializedActors OnActorsInitialized;
    
    DECLARE_EVENT_OneParam(UWorld, FOnNetTickEvent, float);
    DECLARE_EVENT(UWorld, FOnTickFlushEvent);
    /** Event to gather up all net drivers and call TickDispatch at once */
    FOnNetTickEvent TickDispatchEvent;

    /** Event to gather up all net drivers and call PostTickDispatch at once */
    FOnTickFlushEvent PostTickDispatchEvent;

    /** Event to gather up all net drivers and call TickFlush at once */
    FOnNetTickEvent TickFlushEvent;
    
    /** Event to gather up all net drivers and call PostTickFlush at once */
    FOnTickFlushEvent PostTickFlushEvent;
    
    /** Called when the number of levels changes. */
    DECLARE_EVENT(UWorld, FOnLevelsChangedEvent);
    
    /** Broadcasts whenever the number of levels changes */
    FOnLevelsChangedEvent LevelsChangedEvent;
    
    DECLARE_EVENT_OneParam(UWorld, FOnGameStateSetEvent, AGameStateBase*);
    /** Called whenever the gamestate is set on the world. */
    FOnGameStateSetEvent GameStateSetEvent;
};

///
/* Engine\Source\Runtime\Engine\Public\GameDelegates.h */
class ENGINE_API FGameDelegates
{
    /** Return a single FGameDelegates object */
    static FGameDelegates& Get();

    // Called when an exit command is received
    DEFINE_GAME_DELEGATE_TYPED(ExitCommandDelegate, FSimpleMulticastDelegate);

    // Called when ending playing a map
    DEFINE_GAME_DELEGATE_TYPED(EndPlayMapDelegate, FSimpleMulticastDelegate);

    // Called when a matinee is canceled 
    DEFINE_GAME_DELEGATE_TYPED(MatineeCancelledDelegate, FSimpleMulticastDelegate);

    // Called when a pending connection has been lost 
    DEFINE_GAME_DELEGATE_TYPED(PendingConnectionLostDelegate, FPendingConnectionLostDelegate);

    // Called when a player is disconnecting due to network failure
    DEFINE_GAME_DELEGATE(HandleDisconnectDelegate);
};
           

引擎子系統

///
class ENGINE_API FNetDelegates
{
    /**
     * Delegate fired when a pending net game has created a UNetConnection to the server but hasn't sent the initial join message yet.
     *
     * @param PendingNetGame pointer to the PendingNetGame that is initializing its connection to a server.
     */
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnPendingNetGameConnectionCreated, UPendingNetGame* /*PendingNetGame*/);
    static FOnPendingNetGameConnectionCreated OnPendingNetGameConnectionCreated;
};

///
class ENGINE_VTABLE UNetDriver : public UObject, public FExec 
{
#if !UE_BUILD_SHIPPING
    /** Delegate for hooking ProcessRemoteFunction */
    FOnSendRPC    SendRPCDel;
#endif
};

///
class ENGINE_VTABLE UNetConnection : public UPlayer 
{
#if !UE_BUILD_SHIPPING
    /** Delegate for hooking ReceivedRawPacket */
    FOnReceivedRawPacket    ReceivedRawPacketDel;

    /** Delegate for hooking LowLevelSend */
    FOnLowLevelSend            LowLevelSendDel;
#endif
};

///
class ENGINE_API ULevelStreaming : public UObject 
{
    /** Called when level is streamed in  */
    UPROPERTY(BlueprintAssignable)
    FLevelStreamingLoadedStatus            OnLevelLoaded;
    
    /** Called when level is streamed out  */
    UPROPERTY(BlueprintAssignable)
    FLevelStreamingLoadedStatus            OnLevelUnloaded;
    
    /** Called when level is added to the world  */
    UPROPERTY(BlueprintAssignable)
    FLevelStreamingVisibilityStatus        OnLevelShown;
    
    /** Called when level is removed from the world  */
    UPROPERTY(BlueprintAssignable)
    FLevelStreamingVisibilityStatus        OnLevelHidden;
};

///
class ENGINE_API FPhysicsDelegates
{
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnPhysSceneInit, FPhysScene*);
    static FOnPhysSceneInit OnPhysSceneInit;
};

///
class FPhysScene_PhysX 
{
    DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPhysScenePreTick, FPhysScene_PhysX*, float /*DeltaSeconds*/);
    FOnPhysScenePreTick OnPhysScenePreTick;

    DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPhysSceneStep, FPhysScene_PhysX*, float /*DeltaSeconds*/);
    FOnPhysSceneStep OnPhysSceneStep;

    DECLARE_MULTICAST_DELEGATE_OneParam(FOnPhysScenePostTick, FPhysScene*);
    FOnPhysScenePostTick OnPhysScenePostTick;
};

///
class CORE_API FModuleManager : private FSelfRegisteringExec 
{
    /**
     * Gets an event delegate that is executed when the set of known modules changed, i.e. upon module load or unload.
     *
     * The first parameter is the name of the module that changed.
     * The second parameter is the reason for the change.
     *
     * @return The event delegate.
     */
    DECLARE_EVENT_TwoParams(FModuleManager, FModulesChangedEvent, FName, EModuleChangeReason);
    FModulesChangedEvent& OnModulesChanged( )
    {
        return ModulesChangedEvent;
    }

    /**
     * Gets a multicast delegate that is executed when any UObjects need processing after a module was loaded.
     *
     * @return The delegate.
     */
    DECLARE_EVENT_TwoParams(FModuleManager, ProcessLoadedObjectsEvent, FName, bool);
    ProcessLoadedObjectsEvent& OnProcessLoadedObjectsCallback()
    {
        return ProcessLoadedObjectsCallback;
    }

    /**
     * Gets a delegate that is executed when a module containing UObjects has been loaded.
     *
     * The first parameter is the name of the loaded module.
     *
     * @return The event delegate.
     */
    DECLARE_DELEGATE_RetVal_OneParam(bool, FIsPackageLoadedCallback, FName);
    FIsPackageLoadedCallback& IsPackageLoadedCallback()
    {
        return IsPackageLoaded;
    }
};

///
class IGameMoviePlayer 
{
    /** Called before playing a movie if the loading screen has not been prepared. */
    DECLARE_EVENT(IGameMoviePlayer, FOnPrepareLoadingScreen)
    virtual FOnPrepareLoadingScreen& OnPrepareLoadingScreen() = 0;
    
    /* Callback for when the LoadingScreen setup above in WidgetLoadingScreen is displayed **/
    DECLARE_EVENT(IGameMoviePlayer, FOnMoviePlaybackStarted)
    virtual FOnMoviePlaybackStarted& OnMoviePlaybackStarted() = 0;

    DECLARE_EVENT(IGameMoviePlayer, FOnMoviePlaybackFinished)
    virtual FOnMoviePlaybackFinished& OnMoviePlaybackFinished() = 0;

    DECLARE_EVENT_OneParam(IGameMoviePlayer, FOnMovieClipFinished, const FString&)
    virtual FOnMovieClipFinished& OnMovieClipFinished() = 0;
};

///
class ONLINESUBSYSTEM_API FOnlineSubsystemDelegates
{

public:

    /**
     * Notification that a new online subsystem instance has been created
     * 
     * @param NewSubsystem the new instance created
     */
    DECLARE_MULTICAST_DELEGATE_OneParam(FOnOnlineSubsystemCreated, class IOnlineSubsystem* /*NewSubsystem*/);
    static FOnOnlineSubsystemCreated OnOnlineSubsystemCreated;
};

///
class GenericApplication 
{
    DECLARE_EVENT_OneParam(GenericApplication, FOnDisplayMetricsChanged, const FDisplayMetrics&);
    
    /** Notifies subscribers when any of the display metrics change: e.g. resolution changes or monitor sare re-arranged. */
    FOnDisplayMetricsChanged& OnDisplayMetricsChanged(){ return OnDisplayMetricsChangedEvent; }
    
    /** Delegate for virtual keyboard being shown/hidden in case UI wants to slide out of the way */
    DECLARE_EVENT_OneParam(FSlateApplication, FVirtualKeyboardShownEvent, FPlatformRect);
    FVirtualKeyboardShownEvent& OnVirtualKeyboardShown()  { return VirtualKeyboardShownEvent; }
    
    DECLARE_EVENT(FSlateApplication, FVirtualKeyboardHiddenEvent);
    FVirtualKeyboardHiddenEvent& OnVirtualKeyboardHidden()  { return VirtualKeyboardHiddenEvent; }
};


///
class SLATE_API FSlateApplication
{
    static FSlateApplication& Get()
    {
        check( IsInGameThread() || IsInSlateThread() || IsInAsyncLoadingThread() );
        return *CurrentApplication;
    }
    
    /** Event before slate application ticks. */
    DECLARE_EVENT_OneParam(FSlateApplication, FSlateTickEvent, float);
    FSlateTickEvent& OnPreTick()  { return PreTickEvent; }

    /** Event after slate application ticks. */
    FSlateTickEvent& OnPostTick()  { return PostTickEvent; }
    
    /** Delegate called when a window is about to be destroyed */
    DECLARE_EVENT_OneParam(FSlateApplication, FOnWindowBeingDestroyed, const SWindow&);
    FOnWindowBeingDestroyed& OnWindowBeingDestroyed() { return WindowBeingDestroyedEvent; }
    
    /** Sets the handler for otherwise unhandled key down events. This is used by the editor to provide a global action list, if the key was not consumed by any widget. */
    void SetUnhandledKeyDownEventHandler( const FOnKeyEvent& NewHandler );
    
    /** Delegate for when a key down event occurred but was not handled in any other way by ProcessKeyDownMessage */
    FOnKeyEvent UnhandledKeyDownEventHandler;
    
    DECLARE_EVENT_OneParam(FSlateApplication, FApplicationActivationStateChangedEvent, const bool /*IsActive*/)
    virtual FApplicationActivationStateChangedEvent& OnApplicationActivationStateChanged() { return ApplicationActivationStateChangedEvent; }
    
    FApplicationActivationStateChangedEvent ApplicationActivationStateChangedEvent;
};

///
class ENGINE_API UGameViewportClient : public UScriptViewportClient, public FExec
{
    #if WITH_EDITOR
    /** Delegate called when game viewport client received input key */
    FOnGameViewportInputKey GameViewportInputKeyDelegate;
#endif

    /** Delegate called at the end of the frame when a screenshot is captured */
    static FOnScreenshotCaptured ScreenshotCapturedDelegate;
    
    /** Delegate called right after the viewport is rendered */
    static FOnViewportRendered ViewportRenderedDelegate;

    /** Delegate called when a request to close the viewport is received */
    FOnCloseRequested CloseRequestedDelegate;

    /** Delegate called when the window owning the viewport is requested to close */
    FOnWindowCloseRequested WindowCloseRequestedDelegate;

    /** Delegate called when the game viewport is created. */
    static FSimpleMulticastDelegate CreatedDelegate;

    /** Delegate called when a player is added to the game viewport */
    FOnGameViewportClientPlayerAction PlayerAddedDelegate;

    /** Delegate called when a player is removed from the game viewport */
    FOnGameViewportClientPlayerAction PlayerRemovedDelegate;

    /** Delegate called when the engine starts drawing a game viewport */
    FSimpleMulticastDelegate BeginDrawDelegate;

    /** Delegate called when the game viewport is drawn, before drawing the console */
    FSimpleMulticastDelegate DrawnDelegate;

    /** Delegate called when the engine finishes drawing a game viewport */
    FSimpleMulticastDelegate EndDrawDelegate;

    /** Delegate called when ticking the game viewport */
    FOnGameViewportTick TickDelegate;

    /** Delegate called when the engine toggles fullscreen */
    FOnToggleFullscreen ToggleFullscreenDelegate;
};
           

GamePlay架構

///
class ENGINE_API FGameModeEvents
{
public:

    /**
     * GameMode initialization has occurred
     * - Called at the end of AGameModeBase::InitGame 
     * - AGameSession has also been initialized
     * - Possible some child level initialization hasn't finished
     *
     * @param GameMode the game mode actor that has been initialized
     */
    DECLARE_EVENT_OneParam(AGameModeBase, FGameModeInitializedEvent, AGameModeBase* /*GameMode*/);

    /**
     * Client pre login event, triggered when a client first contacts a server
     *
     * @param GameMode the game mode actor that has been initialized
     * @param NewPlayer the unique id of the player attempting to join
     * @param ErrorMessage current state of any error messages, setting this value non empty will reject the player
     */
    DECLARE_EVENT_ThreeParams(AGameModeBase, FGameModePreLoginEvent, AGameModeBase* /*GameMode*/, const FUniqueNetIdRepl& /*NewPlayer*/, FString& /*ErrorMessage*/);

    /** 
     * Post login event, triggered when a player joins the game as well as after non-seamless ServerTravel
     *
     * This is called after the player has finished initialization
     */
    DECLARE_EVENT_TwoParams(AGameModeBase, FGameModePostLoginEvent, AGameModeBase* /*GameMode*/, APlayerController* /*NewPlayer*/);

    /**
     * Logout event, triggered when a player leaves the game as well as during non-seamless ServerTravel
     *
     * Note that this is called before performing any cleanup of the specified AController
     */
    DECLARE_EVENT_TwoParams(AGameModeBase, FGameModeLogoutEvent, AGameModeBase* /*GameMode*/, AController* /*Exiting*/);

    /**
     * Match state has changed via SetMatchState()
     *
     * @param MatchState new match state
     */
    DECLARE_EVENT_OneParam(AGameModeBase, FGameModeMatchStateSetEvent, FName /*MatchState*/);

public: 
    
    static FGameModeInitializedEvent& OnGameModeInitializedEvent() { return GameModeInitializedEvent; } 
    static FGameModePreLoginEvent& OnGameModePreLoginEvent() { return GameModePreLoginEvent; }
    static FGameModePostLoginEvent& OnGameModePostLoginEvent() { return GameModePostLoginEvent; }
    static FGameModeLogoutEvent& OnGameModeLogoutEvent() { return GameModeLogoutEvent; }
    static FGameModeMatchStateSetEvent& OnGameModeMatchStateSetEvent() { return GameModeMatchStateSetEvent; }

    static FGameModeInitializedEvent GameModeInitializedEvent;
    static FGameModePreLoginEvent GameModePreLoginEvent;
    static FGameModePostLoginEvent GameModePostLoginEvent;
    static FGameModeLogoutEvent GameModeLogoutEvent;
    static FGameModeMatchStateSetEvent GameModeMatchStateSetEvent;
};

///
class ENGINE_API AActor : public UObject 
{
    //~==============================================================================================
    // Delegates
    
    /** Called when the actor is damaged in any way. */
    UPROPERTY(BlueprintAssignable, Category="Game|Damage")
    FTakeAnyDamageSignature OnTakeAnyDamage;

    /** Called when the actor is damaged by point damage. */
    UPROPERTY(BlueprintAssignable, Category="Game|Damage")
    FTakePointDamageSignature OnTakePointDamage;

    /** Called when the actor is damaged by radial damage. */
    UPROPERTY(BlueprintAssignable, Category="Game|Damage")
    FTakeRadialDamageSignature OnTakeRadialDamage;
    
    /** 
     * Called when another actor begins to overlap this actor, for example a player walking into a trigger.
     * For events when objects have a blocking collision, for example a player hitting a wall, see 'Hit' events.
     * @note Components on both this and the other Actor must have bGenerateOverlapEvents set to true to generate overlap events.
     */
    UPROPERTY(BlueprintAssignable, Category="Collision")
    FActorBeginOverlapSignature OnActorBeginOverlap;

    /** 
     * Called when another actor stops overlapping this actor. 
     * @note Components on both this and the other Actor must have bGenerateOverlapEvents set to true to generate overlap events.
     */
    UPROPERTY(BlueprintAssignable, Category="Collision")
    FActorEndOverlapSignature OnActorEndOverlap;

    /** Called when the mouse cursor is moved over this actor if mouse over events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Mouse Input")
    FActorBeginCursorOverSignature OnBeginCursorOver;

    /** Called when the mouse cursor is moved off this actor if mouse over events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Mouse Input")
    FActorEndCursorOverSignature OnEndCursorOver;

    /** Called when the left mouse button is clicked while the mouse is over this actor and click events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Mouse Input")
    FActorOnClickedSignature OnClicked;

    /** Called when the left mouse button is released while the mouse is over this actor and click events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Mouse Input")
    FActorOnReleasedSignature OnReleased;

    /** Called when a touch input is received over this actor when touch events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Touch Input")
    FActorOnInputTouchBeginSignature OnInputTouchBegin;
        
    /** Called when a touch input is received over this component when touch events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Touch Input")
    FActorOnInputTouchEndSignature OnInputTouchEnd;

    /** Called when a finger is moved over this actor when touch over events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Touch Input")
    FActorBeginTouchOverSignature OnInputTouchEnter;

    /** Called when a finger is moved off this actor when touch over events are enabled in the player controller. */
    UPROPERTY(BlueprintAssignable, Category="Input|Touch Input")
    FActorEndTouchOverSignature OnInputTouchLeave;

    /** 
     *    Called when this Actor hits (or is hit by) something solid. This could happen due to things like Character movement, using Set Location with 'sweep' enabled, or physics simulation.
     *    For events when objects overlap (e.g. walking into a trigger) see the 'Overlap' event.
     *    @note For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled.
     */
    UPROPERTY(BlueprintAssignable, Category="Collision")
    FActorHitSignature OnActorHit;
};

///
class ENGINE_API UActorComponent : public UObject, public IInterface_AssetUserData
{
    /** Create component physics state global delegate.*/
    static FActorComponentGlobalCreatePhysicsSignature GlobalCreatePhysicsDelegate;
    /** Destroy component physics state global delegate.*/
    static FActorComponentGlobalDestroyPhysicsSignature GlobalDestroyPhysicsDelegate;
    
    /** Called when the component has been activated, with parameter indicating if it was from a reset */
    UPROPERTY(BlueprintAssignable, Category = "Components|Activation")
    FActorComponentActivatedSignature OnComponentActivated;

    /** Called when the component has been deactivated */
    UPROPERTY(BlueprintAssignable, Category = "Components|Activation")
    FActorComponentDeactivateSignature OnComponentDeactivated;
};

///
DECLARE_MULTICAST_DELEGATE_OneParam(FPawnChangedSignature, APawn* /*NewPawn*/);

class ENGINE_API ULocalPlayer : public UPlayer
{
    DECLARE_EVENT_TwoParams(ULocalPlayer, FOnControllerIdChanged, int32 /*NewId*/, int32 /*OldId*/);
    FOnControllerIdChanged& OnControllerIdChanged() const { return OnControllerIdChangedEvent; }
};

///
class ENGINE_API AController : public AActor, public INavAgentInterface 
{
    FInstigatedAnyDamageSignature OnInstigatedAnyDamage;

    FPawnChangedSignature& GetOnNewPawnNotifier() { return OnNewPawn; }
};

///
class ENGINE_API ACharacter : public APawn 
{
    /** Multicast delegate for MovementMode changing. */
    UPROPERTY(BlueprintAssignable, Category=Character)
    FMovementModeChangedSignature MovementModeChangedDelegate;
    
    /**
     * Event triggered at the end of a CharacterMovementComponent movement update.
     * This is the preferred event to use rather than the Tick event when performing custom updates to CharacterMovement properties based on the current state.
     * This is mainly due to the nature of network updates, where client corrections in position from the server can cause multiple iterations of a movement update,
     * which allows this event to update as well, while a Tick event would not.
     *
     * @param    DeltaSeconds        Delta time in seconds for this update
     * @param    InitialLocation        Location at the start of the update. May be different than the current location if movement occurred.
     * @param    InitialVelocity        Velocity at the start of the update. May be different than the current velocity.
     */
    UPROPERTY(BlueprintAssignable, Category=Character)
    FCharacterMovementUpdatedSignature OnCharacterMovementUpdated;
    
    /** Broadcast when Character's jump reaches its apex. Needs CharacterMovement->bNotifyApex = true */
    UPROPERTY(BlueprintAssignable, Category=Character)
    FCharacterReachedApexSignature OnReachedJumpApex;
    
    /**
     * Called upon landing when falling, to perform actions based on the Hit result.
     * Note that movement mode is still "Falling" during this event. Current Velocity value is the velocity at the time of landing.
     * Consider OnMovementModeChanged() as well, as that can be used once the movement mode changes to the new mode (most likely Walking).
     *
     * @param Hit Result describing the landing that resulted in a valid landing spot.
     * @see OnMovementModeChanged()
     */
    FLandedSignature LandedDelegate;
};

///
class ENGINE_API AHUD : public AActor 
{
    // Callback allowing external systems to register to show debug info
    static FOnShowDebugInfo OnShowDebugInfo;

    // Called from ::PostRender. For less player/actor centered debugging
    static FOnHUDPostRender OnHUDPostRender;
};
           

功能庫

///
DECLARE_DELEGATE_ThreeParams(FLoadPackageAsyncDelegate, const FName& /*PackageName*/, UPackage* /*LoadedPackage*/, EAsyncLoadingResult::Type /*Result*/)

/* Engine\Source\Runtime\CoreUObject\Public\UObject\UObjectGlobals.h **/

/**
 * Delegate called on completion of async package loading
 * @param    PackageName            Package name we were trying to load
 * @param    LoadedPackage        Loaded package if successful, nullptr otherwise    
 * @param    Result        Result of async loading.
 */
DECLARE_DELEGATE_ThreeParams(FLoadPackageAsyncDelegate, const FName& /*PackageName*/, UPackage* /*LoadedPackage*/, EAsyncLoadingResult::Type /*Result*/)

/**
 * Asynchronously load a package and all contained objects that match context flags. Non-blocking.
 * This version is useful when loading multiple copies of the same package.
 *
 * @param    InName                    Name of package to load
 * @param    InGuid                    GUID of the package to load, or nullptr for "don't care"
 * @param    InPackageToLoadFrom        If non-null, this is another package name. We load from this package name, into a (probably new) package named InName
 * @param    InCompletionDelegate    Delegate to be invoked when the packages has finished streaming
 * @param    InPackageFlags            Package flags used to construct loaded package in memory
 * @param    InPIEInstanceID            Play in Editor instance ID
 * @param    InPackagePriority        Loading priority
 * @return Unique ID associated with this load request (the same package can be associated with multiple IDs).
 */
COREUOBJECT_API int32 LoadPackageAsync(const FString& InName, const FGuid* InGuid = nullptr, const TCHAR* InPackageToLoadFrom = nullptr, FLoadPackageAsyncDelegate InCompletionDelegate = FLoadPackageAsyncDelegate(), EPackageFlags InPackageFlags = PKG_None, int32 InPIEInstanceID = INDEX_NONE, TAsyncLoadPriority InPackagePriority = 0);

/**
 * Asynchronously load a package and all contained objects that match context flags. Non-blocking.
 *
 * @param    InName                    Name of package to load
 * @param    InCompletionDelegate    Delegate to be invoked when the packages has finished streaming
 * @param    InPackagePriority        Loading priority
 * @param    InPackageFlags            Package flags used to construct loaded package in memory
 * @param    InPIEInstanceID            Play in Editor instance ID
 * @return Unique ID associated with this load request (the same package can be associated with multiple IDs).
 *
 * @see FStreamableManager for an engine-level wrapper
 */
COREUOBJECT_API int32 LoadPackageAsync(const FString& InName, FLoadPackageAsyncDelegate InCompletionDelegate, TAsyncLoadPriority InPackagePriority = 0, EPackageFlags InPackageFlags = PKG_None, int32 InPIEInstanceID = INDEX_NONE);

/**
* Cancels all async package loading requests.
*/
COREUOBJECT_API void CancelAsyncLoading();

///
class UObjectLibrary : public UObject
{
    DECLARE_EVENT_OneParam(UObjectLibrary, FObjectLibraryOnObjectAdded, UObject* /*NewObject*/);
    FObjectLibraryOnObjectAdded& OnObjectAdded() { return OnObjectAddedEvent; }

    DECLARE_EVENT_OneParam(UObjectLibrary, FObjectLibraryOnObjectRemoved, UObject* /*ObjectToRemove*/);
    FObjectLibraryOnObjectRemoved& OnObjectRemoved() { return OnObjectRemovedEvent; }
};

///
class UMG_API UWidgetBlueprintLibrary : public UBlueprintFunctionLibrary
{
    DECLARE_DYNAMIC_DELEGATE(FOnGameWindowCloseButtonClickedDelegate);

    UFUNCTION(BlueprintCallable, Category = "Widget|Window Title Bar")
    static void SetWindowTitleBarOnCloseClickedDelegate(FOnGameWindowCloseButtonClickedDelegate Delegate);
};

///
class ENGINE_API UKismetSystemLibrary : public UBlueprintFunctionLibrary
{
    DECLARE_DYNAMIC_DELEGATE_OneParam(FOnAssetLoaded, class UObject*, Loaded);

    UFUNCTION(BlueprintCallable, meta = (Latent, LatentInfo = "LatentInfo", WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Utilities")
    static void LoadAsset(UObject* WorldContextObject, TSoftObjectPtr<UObject> Asset, FOnAssetLoaded OnLoaded, FLatentActionInfo LatentInfo);

    DECLARE_DYNAMIC_DELEGATE_OneParam(FOnAssetClassLoaded, TSubclassOf<UObject>, Loaded);

    UFUNCTION(BlueprintCallable, meta = (Latent, LatentInfo = "LatentInfo", WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Utilities")
    static void LoadAssetClass(UObject* WorldContextObject, TSoftClassPtr<UObject> AssetClass, FOnAssetClassLoaded OnLoaded, FLatentActionInfo LatentInfo);
};


///
/** Delegate called when a notify was replaced */
DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnNotifyReplaced, UAnimNotify*, OldNotify, UAnimNotify*, NewNotify);

/** Delegate called when a notify state was replaced */
DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnNotifyStateReplaced, UAnimNotifyState*, OldNotifyState, UAnimNotifyState*, NewNotifyState);

/** Blueprint library for altering and analyzing animation / skeletal data */
class ANIMATIONMODIFIERS_API UAnimationBlueprintLibrary : public UBlueprintFunctionLibrary
{
    /** Replaces animation notifies in the specified Animation Sequence */
    UFUNCTION(BlueprintCallable, Category = "AnimationBlueprintLibrary|NotifyEvents")
    static void ReplaceAnimNotifyStates(UAnimSequenceBase* AnimationSequence, TSubclassOf<UAnimNotifyState> OldNotifyClass, TSubclassOf<UAnimNotifyState> NewNotifyClass, FOnNotifyStateReplaced OnNotifyStateReplaced);

    /** Replaces animation notifies in the specified Animation Sequence */
    UFUNCTION(BlueprintCallable, Category = "AnimationBlueprintLibrary|NotifyEvents")
    static void ReplaceAnimNotifies(UAnimSequenceBase* AnimationSequence, TSubclassOf<UAnimNotify> OldNotifyClass, TSubclassOf<UAnimNotify> NewNotifyClass, FOnNotifyReplaced OnNotifyReplaced);
};
           

繼續閱讀