一、在C++中创建可接收事件的接口类EventInterface,继承自UInterface
1、EventInterface.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "EventInterface.generated.h"
UINTERFACE(MinimalAPI)
class UEventInterface : public UInterface
{
GENERATED_BODY()
};
class EVENTDISPATHER_API IEventInterface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, Category = "Event Dispather Utility")
void OnReceiveEvent(UObject* Data);
};
注意:
声明一个接收事件的函数OnReceiveEvent,这里没有用Virtual关键字,是因为Virtual关键字不能在蓝图中使用。
BlueprintNativeEvent标记的函数,在C++中需要通过OnReceiveEvent_Implement来实现,在蓝图中也可以调出OnReceiveEvent事件节点。
蓝图中如果调用父类的OnReceiveEvent函数,就是先调用C++版本的OnReceiveEvent_Implement函数。
2、EventInterface.cpp
#include "EventInterface.h"
二、在C++中创建事件管理器类CustomEventManager,继承自BlueprintFunctionLibrary
1、CustomEventManager.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "CustomEventManager.generated.h"
UCLASS()
class EVENTDISPATHER_API UCustomEventManager : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
private:
static TMap<FString, TArray<UObject*>> AllListeners;
public:
UFUNCTION(BlueprintCallable, Category = "Event Dispather Utility")
static void AddEventListener(FString EventName, UObject* Listener);
UFUNCTION(BlueprintCallable, Category = "Event Dispather Utility")
static void RemoveEventListener(FString EventName, UObject* Listener);
UFUNCTION(BlueprintCallable, Category = "Event Dispather Utility")
static FString DispatchEvent(FString EventName, UObject* Data);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Event Dispather Utility")
static UObject* NewAsset(UClass* ClassType);
};
注意:事件管理器包含了下面函数
添加事件监听AddEventListener
移除事件监听RemoveEventListener
发送事件DispatchEvent
初始化事件参数NewAsset
2、CustomEventManager.cpp
#include "CustomEventManager.h"
#include "EventInterface.h"
#include "Engine.h"
TMap<FString, TArray<UObject*>> UCustomEventManager::AllListeners;
void UCustomEventManager::AddEventListener(FString EventName, UObject* Listener)
{
//表示指针为nullptr但是可能还没有被垃圾回收
//所以需要IsValidLowLevel判断底层是否有效
//ImplementsInterface用于判断是否实现了指定的接口
if (EventName == "" || Listener == nullptr || !Listener->IsValidLowLevel() || !Listener->GetClass()->ImplementsInterface(UEventInterface::StaticClass()))
{
return;
}
TArray<UObject*>* Arr = UCustomEventManager::AllListeners.Find(EventName);
if (Arr == nullptr || Arr->Num() == 0)
{
TArray<UObject*> NewArr = { Listener };
UCustomEventManager::AllListeners.Add(EventName, NewArr);
}
else
{
Arr->Add(Listener);
}
}
void UCustomEventManager::RemoveEventListener(FString EventName, UObject* Listener)
{
TArray<UObject*>* Arr = UCustomEventManager::AllListeners.Find(EventName);
if (Arr != nullptr && Arr->Num() != 0)
{
Arr->Remove(Listener);
}
}
FString UCustomEventManager::DispatchEvent(FString EventName, UObject* Data)
{
TArray<UObject*>* Arr = UCustomEventManager::AllListeners.Find(EventName);
if (Arr == nullptr || Arr->Num() == 0)
{
return "'" + EventName + "' No Listener.";
}
FString ErrorInfo = "\n";
for (int i = 0; i < Arr->Num(); i++)
{
UObject* Obj = (*Arr)[i];
if (Obj == nullptr || !Obj->IsValidLowLevel() || !Obj->GetClass()->ImplementsInterface(UEventInterface::StaticClass()))
{
Arr->RemoveAt(i--);
}
else
{
UFunction* Fun = Obj->FindFunction("OnReceiveEvent");
if (Fun == nullptr || !Fun->IsValidLowLevel())
{
ErrorInfo += "'" + Obj->GetName() + "' No 'OnReceiveEvent' Function. \n";
}
else
{
Obj->ProcessEvent(Fun, &Data);
}
}
}
return ErrorInfo;
}
UObject* UCustomEventManager::NewAsset(UClass* ClassType)
{
//GetTransientPackage获取临时的包,将Obj生成进去
UObject* Obj = NewObject<UObject>(GetTransientPackage(), ClassType);
return Obj;
}
三、在C++中创建事件参数类MyData,继承自UObject
1、MyData.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyData.generated.h"
UCLASS(Blueprintable)
class EVENTDISPATHER_API UMyData : public UObject
{
GENERATED_BODY()
public:
UMyData();
UPROPERTY(BlueprintReadWrite)
int Param;
};
2、MyData.cpp
#include "MyData.h"
UMyData::UMyData()
{
}
四、在C++中发送、接收和移除事件
1、发送事件
#include "../EventDispatherUtility/CustomEventManager.h"
#include "MyData.h"
void AMyBpAndCpp_Sender::BeginPlay()
{
UMyData* Data = Cast<UMyData>(UCustomEventManager::NewAsset(UMyData::StaticClass()));
Data->Param = FMath::RandRange(0, 100);
UCustomEventManager::DispatchEvent("MyBpAndCpp_DispatchEvent", Data);
}
2、接收和移除事件
MyBpAndCpp_Receive_G.h
#pragma once
#include "CoreMinimal.h"
#include "MyBpAndCpp_Receive_Parent.h"
#include "../EventDispatherUtility/EventInterface.h"
#include "MyBpAndCpp_Receive_G.generated.h"
UCLASS()
class EVENTDISPATHER_API AMyBpAndCpp_Receive_G : public AMyBpAndCpp_Receive_Parent,public IEventInterface
{
GENERATED_BODY()
protected:
virtual void BeginPlay() override;
virtual void BeginDestroy() override;
public:
void OnReceiveEvent_Implementation(UObject* Data) override;
};
MyBpAndCpp_Receive_G.cpp
#include "MyBpAndCpp_Receive_G.h"
#include "Engine/Engine.h"
#include "MyData.h"
#include "../EventDispatherUtility/CustomEventManager.h"
#include "TimerManager.h"
void AMyBpAndCpp_Receive_G::BeginPlay()
{
Super::BeginPlay();
UCustomEventManager::AddEventListener("MyBpAndCpp_DispatchEvent", this);
FTimerHandle TimerHandle;
auto Lambda = [this]()
{
UCustomEventManager::RemoveEventListener("MyBpAndCpp_DispatchEvent", this);
};
//GetWorld()->GetTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda(Lambda), 5.0f, false);
}
void AMyBpAndCpp_Receive_G::BeginDestroy()
{
UCustomEventManager::RemoveEventListener("MyBpAndCpp_DispatchEvent", this);
Super::BeginDestroy();
}
void AMyBpAndCpp_Receive_G::OnReceiveEvent_Implementation(UObject* Data)
{
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 10.0f, FColor::Green, FString::Printf(TEXT("%i"), Cast<UMyData>(Data)->Param));
}
五、在C++中发送事件,在蓝图中监听、接收、移除事件
1、C++发送事件同上
2、在蓝图中监听、接收、移除事件
六、在蓝图中发送、监听、接收、移除事件,
1、在蓝图中发送事件
2、在蓝图中监听、接收、移除事件