Unity 游戏框架搭建 2019 (四十八/四十九) MonoBehaviourSimplify 中的消息策略完善&关于发送事件的简单封装 (2)

我们发现,在申请对象部分可以简化成如下:

// var msgRecord = MsgRecord.Allocate(); // // msgRecord.Name = msgName; // msgRecord.OnMsgReceived = onMsgReceived; // // mMsgRecorder.Add(msgRecord); mMsgRecorder.Add(MsgRecord.Allocate(msgName, onMsgReceived));

只需要向 MsgRecord.Allocate 增加参数,代码如下:

public static MsgRecord Allocate(string msgName,Action<object> onMsgReceived) { MsgRecord retMsgRecord = null; retMsgRecord = mMsgRecordPool.Count > 0 ? mMsgRecordPool.Pop() : new MsgRecord(); retMsgRecord.Name = msgName; retMsgRecord.OnMsgReceived = onMsgReceived; return retMsgRecord; }

代码不难,那么到这里,我们的完整的第十三个示例就写完了。

完整示例代码如下:

using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace QFramework { public abstract partial class MonoBehaviourSimplify { List<MsgRecord> mMsgRecorder = new List<MsgRecord>(); private class MsgRecord { private static readonly Stack<MsgRecord> mMsgRecordPool = new Stack<MsgRecord>(); public static MsgRecord Allocate(string msgName,Action<object> onMsgReceived) { MsgRecord retMsgRecord = null; retMsgRecord = mMsgRecordPool.Count > 0 ? mMsgRecordPool.Pop() : new MsgRecord(); retMsgRecord.Name = msgName; retMsgRecord.OnMsgReceived = onMsgReceived; return retMsgRecord; } public void Recycle() { Name = null; OnMsgReceived = null; mMsgRecordPool.Push(this); } public string Name; public Action<object> OnMsgReceived; } protected void RegisterMsg(string msgName, Action<object> onMsgReceived) { MsgDispatcher.Register(msgName, onMsgReceived); mMsgRecorder.Add(MsgRecord.Allocate(msgName, onMsgReceived)); } private void OnDestroy() { OnBeforeDestroy(); foreach (var msgRecord in mMsgRecorder) { MsgDispatcher.UnRegister(msgRecord.Name,msgRecord.OnMsgReceived); msgRecord.Recycle(); } mMsgRecorder.Clear(); } protected abstract void OnBeforeDestroy(); } public class MsgDistapcherInMonoBehaviourSimplify : MonoBehaviourSimplify { #if UNITY_EDITOR [UnityEditor.MenuItem("QFramework/13.消息机制集成到 MonoBehaviourSimplify", false, 14)] private static void MenuClicked() { UnityEditor.EditorApplication.isPlaying = true; new GameObject("MsgReceiverObj") .AddComponent<MsgDistapcherInMonoBehaviourSimplify>(); } #endif private void Awake() { RegisterMsg("Do", DoSomething); RegisterMsg("Do", DoSomething); RegisterMsg("DO1", _ => { }); RegisterMsg("DO2", _ => { }); RegisterMsg("DO3", _ => { }); } private IEnumerator Start() { MsgDispatcher.Send("Do","hello"); yield return new WaitForSeconds(1.0f); MsgDispatcher.Send("Do","hello1"); } void DoSomething(object data) { // do something Debug.LogFormat("Received Do msg:{0}",data); } protected override void OnBeforeDestroy() { } } }

运行结果如下图:

菜单栏如下图:

目录如下图:

006tNc79gy1fzft5i5y2ej30gm0dimz9.jpg

到这里我们可以进行一次导出了。

关于发送事件的简单封装

在上一篇,我们在 MonoBehaviourSimplify 中集成了消息功能。而在做消息功能的过程中,又接触了对象池实现了一个非常简单版本。

今天呢我们在接着学习。

我们先回顾下 MonoBehaviourSimplify 中关于消息功能的使用方法。

注册消息,直接用 RegisterMsg,而注销则在 OnDestroy 的时候统一进行注销。
那么单独注销时候怎么办呢?这是第一个问题。

第二个问题是,发送消息,我们使用的是 MsgDispatcher.Send 这个方法。
和我们的注册消息的方法不是统一的。这是第二个问题。

第一个问题

第一个问题解决很简单,只要增加针对一个消息注销的方法就好了。
代码如下:

public partial class MonoBehaviourSimplify { protected void UnRegisterMsg(string msgName) { var selectedRecords = mMsgRecorder.FindAll(recorder => recorder.Name == msgName); selectedRecords.ForEach(selectRecord => { MsgDispatcher.UnRegister(selectRecord.Name, selectRecord.OnMsgReceived); mMsgRecorder.Remove(selectRecord); selectRecord.Recycle(); }); selectedRecords.Clear(); } protected void UnRegisterMsg(string msgName, Action<object> onMsgReceived) { var selectedRecords = mMsgRecorder.FindAll(recorder => recorder.Name == msgName && recorder.OnMsgReceived == onMsgReceived); selectedRecords.ForEach(selectRecord => { MsgDispatcher.UnRegister(selectRecord.Name, selectRecord.OnMsgReceived); mMsgRecorder.Remove(selectRecord); selectRecord.Recycle(); }); selectedRecords.Clear(); } }

FindAll 是一个查询方法,在 mMsgRecorder 内查询出所有符合条件的项。代码没有太大的难度。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspgfz.html