Message Manager 设计思路学习
设计思路
设计项目中不同类之间的消息通信和分发系统时,可以考虑以下思路:
- 定义消息类型:使用枚举或常量定义所有可能的消息类型,这有助于保持系统的可维护性和可扩展性。
- 消息中心:创建一个中央消息管理器或事件总线,它负责接收和分发消息。这个中心应该是线程安全的,以处理并发情况。
- 注册和注销:允许类或对象注册和注销对特定消息类型的监听。这样可以实现灵活的消息处理和减少不必要的处理开销。
- 消息处理:在处理消息时,考虑使用回调函数或处理器类,这样可以清晰地分离消息的接收和处理逻辑。
- 解耦:尽量使发送方和接收方解耦,通过消息中心来传递消息,避免直接的依赖关系。
- 性能考虑:如果消息处理频繁,确保系统对高频消息的处理效率足够高,避免性能瓶颈。
通过这些设计思路,你可以构建一个高效且可维护的消息通信系统。
Message.h
所有消息类型的枚举
UENUM(BlueprintType)
enum EMessageType {
// 初始化,加载一系列
Message_Init,
Message_LoadScene,
Message_LoadAssetList,
Message_LoadGroupList,
Message_LoadAssetTexture,
Message_LoadAssetPak,
Message_LoadAssetCollectTexture,
Message_LoadAssetGroupTexture,
Message_LoadMaterialPak,
Message_LoadGroupPak,
Message_LoadColorCardList,
Message_LoadColorCard,
// 单例初始化
Message_SingletonInit,
Message_ChangeTextureStateToIsReplace,
Message_SingleGridClick,
Message_RefreshButtonClick,
// UI点击
Message_TagClick,
Message_TextureClick,
Message_FurnitureTextureClick,
Message_MaterialTextureClick,
Message_ReplaceFurnitureTextureClick,
Message_GroupTextureClick,
Message_RoomObjectTextureClick,
Message_SceneTextureClick,
Message_TagUIClick,
Message_LoadFurnitureList,
// 物体操作
Message_ActorLocationChange,
Message_ActorDelete,
Message_CopyRoomComponentDelete,
Message_GroupComponentLocationChange,
Message_RoomPlanDelete,
Message_UnSelectActor,
// 下载Pak
Message_DownLoadPakClick,
Message_RemoveGroup,
Message_ClickIsConfirm,
Message_EnterVR,
Message_SingleGridHover,
Message_SingleGridUnHover,
Message_SetFullScreen,
Message_CompanyItemClick,
Message_OnSaveGroupComplete,
Message_ChangeCompanyId,
Message_OnScreenshotClick,
Message_OnBestViewClick,
Message_LoadNormalPackage,
Message_LoadNormalTexture,
Message_LoadNormalThumbnailTexture,
Message_ExportTextureToMaterialPackage,
Message_ExportMaterialPackageComplete,
Message_OpenLevel,
Message_LoadClientTextureList,
Message_LoadClientPlanTextureList,
Message_LoadPlan,
Message_UnselectPostRoomPlanTexture,
};
消息类单例
UCLASS()
class UMessage : public UObject {
GENERATED_BODY()
public:
UMessage() {};
~UMessage() {};
template< class T >
static T* Get() {
static T* instance;
if (instance == NULL) {
instance = NewObject<T>();
instance->AddToRoot();
}
return instance;
};
};
MessageManager
单例管理
#pragma once
#include "UObject/NoExportTypes.h"
#include "Singleton.h"
#include "../Message/Message.h"
#include "Runtime/Core/Public/Delegates/DelegateInstanceInterface.h"
#include "MessageManager.generated.h"
// 声明多播委托,委托名为MessageCallback,传递 UMessage* 类型
DECLARE_MULTICAST_DELEGATE_OneParam(MessageCallback, UMessage*);
UCLASS()
class UMessageManager : public UObject
{
GENERATED_BODY()
public:
UMessageManager();
~UMessageManager();
void Init();
// 根据消息类型,对应不同的委托,方便后续管理
TMap<EMessageType, MessageCallback> MessageCallbackMap;
void RegistMessage(EMessageType messageType, UObject* object, FString funcName);
void UnRegistMessage(EMessageType messageType);
void ExecuteMessage(EMessageType messageType, UMessage* baseMessage);
UFUNCTION()
static UMessageManager* Get();
};
- 注册:void Register Message(
EMessageType messageType
,UObject* object
,FString funcName
); - 注销:void Unregister Message (
EMessageType messageType
); - 执行:void Execute Message (
EMessageType messageType
,UMessage* baseMessage
);
Register Message
通过 Message Callback Map [message Type] 去存储对应消息类型的 Callback
如果包含则替换,不包含就添加
void UMessageManager::RegistMessage(EMessageType messageType, UObject* object, FString funcName) {
MessageCallback messageCallback;
bool bContains = false;
if (MessageCallbackMap.Contains(messageType)) {
messageCallback = MessageCallbackMap[messageType];
bContains = true;
}
messageCallback.AddUFunction(object, *funcName);
if (bContains) {
MessageCallbackMap[messageType] = messageCallback;
}
else {
MessageCallbackMap.Add(messageType, messageCallback);
}
}
UnRegist Message
Message Callback Map [message Type] 移除对应类型的Callback
void UMessageManager::UnRegistMessage(EMessageType messageType)
{
if (MessageCallbackMap.Contains(messageType))
MessageCallbackMap.Remove(messageType);
}
Execute Message
如果存在该消息类型的Callback,则直接调用广播
void UMessageManager::ExecuteMessage(EMessageType messageType, UMessage* baseMessage) {
if (!MessageCallbackMap.Contains(messageType))
return;
MessageCallbackMap[messageType].Broadcast(baseMessage);
}
Event Message.h
该类继承至 Message
类
UEventMessage
类的主要作用是作为一种通用的消息载体,用于在系统中传递多种类型的数据。它提供了多种方法来设置数据并返回自身,以便于 链式调用 ,这种设计模式使得在创建和配置消息对象时更加灵活和简洁。
UCLASS()
class UEventMessage : public UMessage
{
GENERATED_BODY()
public:
bool bValue;
float fValue;
int16 shortValue;
int32 iValue;
uint32 uintValue;
FString sValue;
void* ptr;
UEventMessage* SetBool(bool _bValue){
bValue = _bValue;
return Get<UEventMessage>();
}
UEventMessage* SetFloat(float _fValue) {
fValue = _fValue;
return Get<UEventMessage>();
}
UEventMessage* SetPtr(void* _ptr) {
ptr = _ptr;
return Get<UEventMessage>();
}
UEventMessage* SetInt(int32 _iValue) {
iValue = _iValue;
return Get<UEventMessage>();
}
UEventMessage* SetShort(int16 _iValue) {
shortValue = _iValue;
return Get<UEventMessage>();
}
UEventMessage* SetUInt(uint32 _iValue) {
uintValue = _iValue;
return Get<UEventMessage>();
}
UEventMessage* SetString(FString& _sValue) {
sValue = _sValue;
return Get<UEventMessage>();
}
static UEventMessage* Instance() {
return Get<UEventMessage>();
}
};
Other Class
在其他类中,初始构建时注册消息
UMessageManager::Get()->RegistMessage(EMessageType::Message_TextureClick, this, "OnTextureClick");
UMessageManager::Get()->RegistMessage(EMessageType::Message_MaterialTextureClick, this, "OnMaterialTextureClick");
UMessageManager::Get()->RegistMessage(EMessageType::Message_GroupTextureClick, this, "OnGroupTextureClick");
UMessageManager::Get()->RegistMessage(EMessageType::Message_ReplaceFurnitureTextureClick, this, "OnReplaceFurnitureTextureClick");
UMessageManager::Get()->RegistMessage(EMessageType::Message_TagUIClick, this, "OnTagUIClick");
UMessageManager::Get()->RegistMessage(EMessageType::Message_LoadFurnitureList, this, "HandleFurnitureListMessage");
UMessageManager::Get()->RegistMessage(EMessageType::Message_LoadAssetPak, this, "OnTextureUpdate");
调用消息广播,并把自己作为指针存储至Message
,广播出去
void UGroupUI::OnDownLoadButtonClick() {
bOnlyDownLoad = true;
UMessageManager::Get()->ExecuteMessage(MessageType, UMessage::Get<UEventMessage>()->SetPtr(this));
bOnlyDownLoad = false;
DownLoadButton->SetVisibility(ESlateVisibility::Hidden);
}
当消息广播出去后,接受到消息则调用绑定函数,并可以从Message
拿到所需的数据
void UCategoryUI::OnGroupTextureClick(UEventMessage* message)
{
UGroupUI* groupUI = static_cast<UGroupUI*>(message->ptr);
标签:EMessageType,Get,void,messageType,UMessageManager,Manager,思路,Message
From: https://www.cnblogs.com/Dreammoon/p/18369081