Message Manager 设计思路学习

Message Manager 设计思路学习

设计思路

设计项目中不同类之间的消息通信和分发系统时,可以考虑以下思路:

  1. 定义消息类型:使用枚举或常量定义所有可能的消息类型,这有助于保持系统的可维护性和可扩展性。
  2. 消息中心:创建一个中央消息管理器或事件总线,它负责接收和分发消息。这个中心应该是线程安全的,以处理并发情况。
  3. 注册和注销:允许类或对象注册和注销对特定消息类型的监听。这样可以实现灵活的消息处理和减少不必要的处理开销。
  4. 消息处理:在处理消息时,考虑使用回调函数或处理器类,这样可以清晰地分离消息的接收和处理逻辑。
  5. 解耦:尽量使发送方和接收方解耦,通过消息中心来传递消息,避免直接的依赖关系。
  6. 性能考虑:如果消息处理频繁,确保系统对高频消息的处理效率足够高,避免性能瓶颈。

通过这些设计思路,你可以构建一个高效且可维护的消息通信系统。

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);
posted @   Dream_moon  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示