当前位置:   article > 正文

Unity 工具类 之 简单的消息机制 MessageCenter 实现_unityinstance.sendmessage

unityinstance.sendmessage

Unity 工具类 之 简单的消息机制 MessageCenter 实现

 

目录

Unity 工具类 之 简单的消息机制 MessageCenter 实现

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码


 

一、简单介绍

Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

消息机制,也可以叫做观察者设计模式;通俗易懂点讲,就是 一个物体发出消息,另外一个,或者几个物体可以同时接收到这一消息并作出各自不同的行为(反馈,处理)。

 

二、实现原理

1、消息机制中引入了事件机制,事件机制其实是一种叫做观察者模式的设计模式,事件的本质是一种方法的委托(Delegate),把回调方法委托到事件管理器,当条件达到时,通过事件key来告诉事件管理器可以执行那些委托的方法。

2、单例类,保证整个场景中只有一个类管理消息;把消息统一在一起注册、发送和移除;

3、MessageCenter.Instance.RegisterListener 注册消息;

4、MessageCenter.Instance.SendMessage 发送消息;

5、MessageCenter.Instance.RemoveListener 移除消息;

 

三、注意事项

1、为了避免 MessageCenter 单例被 new ,所以在 MessageCenter 中把 无参构造函数私有化;

2、一个消息可注册多个事件;

 

四、效果预览

 

五、实现步骤

1、打开Unity,新建一个工程,如下图

 

2、在工程中新建脚本,Singleton 实现单例类,Message 消息(可以根据需要拓展),MessageCenter 消息中心管理消息的注册发送与移除(可以根据需要拓展),Test_MessageCenter 测试消息机制脚本、如下图

 

3、在场景中添加测试脚本,进行消息机制的测试,如下图

 

4、测试效果如下图

 

六、关键代码

1、Singleton

  1. using System;
  2. using System.Reflection;
  3. /// <summary>
  4. /// 单例
  5. /// 继承需要一个非公有的无参构造函数
  6. /// </summary>
  7. /// <typeparam name="T">类名的泛型</typeparam>
  8. public abstract class Singleton<T> where T : class
  9. {
  10. private static T instance = null;
  11. // 多线程安全机制
  12. private static readonly object locker = new object();
  13. public static T Instance
  14. {
  15. get
  16. {
  17. // 线程锁
  18. lock (locker)
  19. {
  20. if (null == instance)
  21. {
  22. // 反射获取实例
  23. var octors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic) ;
  24. // 获取无参数的非公共构造函数
  25. var octor = Array.Find(octors, c => c.GetParameters().Length == 0);
  26. // 没有则提示没有私有的构造函数
  27. if (null == octor)
  28. {
  29. throw new Exception("No NonPublic constructor without 0 parameter");
  30. }
  31. // 实例化
  32. instance = octor.Invoke(null) as T;
  33. }
  34. return instance;
  35. }
  36. }
  37. }
  38. /// <summary>
  39. /// 构造函数
  40. /// 避免外界new
  41. /// </summary>
  42. protected Singleton() { }
  43. }

 

2、Message

  1. /// <summary>
  2. /// 消息类
  3. /// </summary>
  4. public class Message
  5. {
  6. public int Type //发送的消息类型
  7. {
  8. get;
  9. private set;
  10. }
  11. public object Body //消息主体
  12. {
  13. get;
  14. private set;
  15. }
  16. /// <summary>
  17. /// 构造函数
  18. /// </summary>
  19. /// <param name="type">消息类型</param>
  20. /// <param name="body">消息体</param>
  21. public Message(int type, object body)
  22. {
  23. Type = type;
  24. Body = body;
  25. }
  26. }

 

3、MessageCenter

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. /// <summary>
  5. /// 消息的类型
  6. /// </summary>
  7. public enum MessageType
  8. {
  9. /// <summary>
  10. /// 启动
  11. /// </summary>
  12. START_UP = 1000,
  13. /// <summary>
  14. /// 解压
  15. /// </summary>
  16. UNPACK,
  17. /// <summary>
  18. /// 更新
  19. /// </summary>
  20. UPDATE,
  21. /// <summary>
  22. /// 更新完成
  23. /// </summary>
  24. UPDATE_COMPLETE,
  25. }
  26. /// <summary>
  27. /// 战斗的类型
  28. /// </summary>
  29. public enum BattleEvent
  30. {
  31. /// <summary>
  32. /// 攻击
  33. /// </summary>
  34. Attack = 10000,
  35. }
  36. /// <summary>
  37. /// 协议的类型
  38. /// </summary>
  39. public enum ProtocolEvent
  40. {
  41. }
  42. /// <summary>
  43. /// 消息中心
  44. /// </summary>
  45. public class MessageCenter : Singleton<MessageCenter>
  46. {
  47. // 消息委托
  48. public delegate void messageDelHandle(Message message);
  49. // 消息字典
  50. private Dictionary<int, messageDelHandle> messageMap = new Dictionary<int, messageDelHandle>();
  51. /// <summary>
  52. /// 构造函数
  53. /// 避免外界new
  54. /// </summary>
  55. private MessageCenter() { }
  56. /// <summary>
  57. /// 注册监听
  58. /// </summary>
  59. public void RegisterListener(int messageType, messageDelHandle handle)
  60. {
  61. if (handle == null) return;
  62. // 把事件添加到对应的委托中
  63. messageDelHandle myHandle = null;
  64. messageMap.TryGetValue(messageType, out myHandle);
  65. messageMap[messageType] = (messageDelHandle)Delegate.Combine(myHandle, handle);
  66. }
  67. /// <summary>
  68. /// 移除监听
  69. /// </summary>
  70. public void RemoveListener(int messageType, messageDelHandle handle)
  71. {
  72. if (handle == null) return;
  73. messageMap[messageType] = (messageDelHandle)Delegate.Remove(messageMap[messageType], handle);
  74. }
  75. /// <summary>
  76. /// 清空消息
  77. /// </summary>
  78. public void Clear()
  79. {
  80. messageMap.Clear();
  81. }
  82. /// <summary>
  83. /// 发送消息
  84. /// </summary>
  85. /// <param name="messageName">消息类型 </param>
  86. /// <param name="body"> 发送消息主体 </param>
  87. public void SendMessage(int messageType, object body = null)
  88. {
  89. messageDelHandle handle;
  90. if (messageMap.TryGetValue(messageType, out handle))
  91. {
  92. Message evt = new Message(messageType, body);
  93. try
  94. {
  95. if (handle != null)
  96. {
  97. handle(evt);
  98. }
  99. }
  100. catch (System.Exception e)
  101. {
  102. Debug.Print("SendMessage:", evt.Type.ToString(), e.Message, e.StackTrace, e);
  103. }
  104. }
  105. }
  106. #region 枚举类型接口
  107. #region MessageType
  108. public void RegisterListener(MessageType messageType, messageDelHandle handle) {
  109. RegisterListener((int)messageType, handle);
  110. }
  111. public void RemoveListener(MessageType messageType, messageDelHandle handle)
  112. {
  113. RemoveListener((int) messageType, handle);
  114. }
  115. public void SendMessage(MessageType messageType, object body = null) {
  116. SendMessage((int)messageType, body);
  117. }
  118. #endregion
  119. #region BattleEvent
  120. public void RegisterListener(BattleEvent messageType, messageDelHandle handle)
  121. {
  122. RegisterListener((int)messageType, handle);
  123. }
  124. public void RemoveListener(BattleEvent messageType, messageDelHandle handle)
  125. {
  126. RemoveListener((int)messageType, handle);
  127. }
  128. public void SendMessage(BattleEvent messageType, object body = null)
  129. {
  130. SendMessage((int)messageType, body);
  131. }
  132. #endregion
  133. #region ProtocolEvent
  134. public void RegisterListener(ProtocolEvent messageType, messageDelHandle handle)
  135. {
  136. RegisterListener((int)messageType, handle);
  137. }
  138. public void RemoveListener(ProtocolEvent messageType, messageDelHandle handle)
  139. {
  140. RemoveListener((int)messageType, handle);
  141. }
  142. public void SendMessage(ProtocolEvent messageType, object body = null)
  143. {
  144. SendMessage((int)messageType, body);
  145. }
  146. #endregion
  147. #endregion
  148. }

 

4、Test_MessageCenter

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class Test_MessageCenter : MonoBehaviour
  5. {
  6. // Start is called before the first frame update
  7. void Start()
  8. {
  9. MessageCenter.Instance.RegisterListener(MessageType.START_UP, StartUp); //注册
  10. MessageCenter.Instance.RegisterListener(MessageType.START_UP, StartUp2); //注册
  11. }
  12. // Update is called once per frame
  13. void Update()
  14. {
  15. if (Input.GetKeyDown(KeyCode.A)) {
  16. MessageCenter.Instance.SendMessage(MessageType.START_UP,this.gameObject);
  17. }
  18. if (Input.GetKeyDown(KeyCode.D))
  19. {
  20. MessageCenter.Instance.RemoveListener(MessageType.START_UP, StartUp2);
  21. }
  22. }
  23. private void StartUp(Message message)
  24. {
  25. Debug.Log("游戏启动");
  26. Debug.Log(message.Type);
  27. Debug.Log(message.Body);
  28. }
  29. private void StartUp2(Message message)
  30. {
  31. Debug.Log("游戏启动2");
  32. Debug.Log(message.Type);
  33. Debug.Log(message.Body);
  34. }
  35. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/126815
推荐阅读
相关标签
  

闽ICP备14008679号