当前位置:   article > 正文

Unity常用设计模式-观察者模式:游戏中的事件传播_unity观察者模式

unity观察者模式

一、简介

       当在Unity中应用观察者模式时,通常是为了实现一种解耦和灵活性较强的事件机制。观察者模式允许一个对象(称为主题)维护一组依赖于它的对象(称为观察者),当主题的状态发生变化时,所有观察者都能够得到通知并进行相应的处理。

二、观察者模式的优势

  1. 松耦合
            观察者模式通过将主题和观察者解耦,使得它们之间的依赖关系更加松散。主题并不需要知道观察者的具体类别,只需知道它们实现了相同的接口或继承了相同的基类。这使得系统更容易维护和扩展。
  2. 可维护性和可扩展性
            由于主题和观察者之间的解耦,系统更容易维护。在不修改主题的情况下,可以轻松地添加或删除观察者,从而扩展系统的功能。
  3. 事件驱动的设计
           观察者模式天然支持事件驱动的设计。主题的状态变化会触发事件,通知所有观察者进行相应的处理。这在Unity中特别有用,例如在游戏中处理用户输入、游戏状态变化等。
  4. 多播通知
           观察者模式允许一个主题同时通知多个观察者。这意味着可以有多个对象独立地响应主题的变化,而不需要主题知道观察者的具体数量或类型。
  5. 解耦 UI 和数据
           在游戏开发中,观察者模式经常用于解耦UI和底层数据。当数据发生变化时,通过观察者模式通知UI进行更新,使得UI可以保持与数据的同步。
  6. 易于理解和维护
           观察者模式是一种经典的设计模式,因此它的使用方式是广泛接受的。这使得代码更易于理解,也更容易维护,因为开发人员可以更容易地理解和预测代码的行为。

        总体而言,观察者模式在Unity中的应用能够提高代码的灵活性、可维护性和可扩展性,是一种强大的设计模式。

三、观察者模式的具体适用案例

观察者模式在Unity当中的适用场景有很多,下面主要介绍的是事件管理器的应用,直接上代码。

  1. using Mr.Le.Utility.Singleton;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.Events;
  7. namespace Mr.Le.Utility.Manager
  8. {
  9. /// <summary>
  10. /// 事件管理器
  11. /// </summary>
  12. public class EventCenterManager : NoMonoSingleton<EventCenterManager>
  13. {
  14. /// <summary>
  15. /// 用于里氏替换的接口
  16. /// </summary>
  17. private interface IEventInfo
  18. {
  19. }
  20. //事件集合
  21. private Dictionary<string, IEventInfo> _events = new Dictionary<string, IEventInfo>();
  22. #region 无参事件
  23. private class EventInfo : IEventInfo
  24. {
  25. public UnityAction action;
  26. /// <summary>
  27. /// 构造函数添加事件
  28. /// </summary>
  29. /// <param name="call"></param>
  30. public EventInfo(UnityAction call)
  31. {
  32. action += call;
  33. }
  34. }
  35. /// <summary>
  36. /// 添加事件监听
  37. /// </summary>
  38. /// <param name="command"></param>
  39. /// <param name="call"></param>
  40. public void AddEventListener(object command, UnityAction call)
  41. {
  42. string name = command.GetType().Name + "_" + command;
  43. if (_events.ContainsKey(name))
  44. {
  45. (_events[name] as EventInfo).action += call;
  46. }
  47. else
  48. {
  49. _events.Add(name, new EventInfo(call));
  50. }
  51. }
  52. /// <summary>
  53. /// 移除指定事件的指定监听
  54. /// </summary>
  55. /// <param name="command"></param>
  56. /// <param name="call"></param>
  57. public void RemoveEventListener(object command, UnityAction call)
  58. {
  59. string name = command.GetType().Name + "_" + command;
  60. if (_events.ContainsKey(name))
  61. {
  62. (_events[name] as EventInfo).action -= call;
  63. }
  64. else
  65. {
  66. Debug.LogError($"{name}事件不存在!");
  67. return;
  68. }
  69. }
  70. /// <summary>
  71. /// 移除指定事件的所有监听
  72. /// </summary>
  73. /// <param name="command"></param>
  74. public void RemoveAllEventListeners(object command)
  75. {
  76. string name = command.GetType().Name + "_" + command;
  77. if (_events.ContainsKey(name))
  78. {
  79. (_events[name] as EventInfo).action = null;
  80. }
  81. else
  82. {
  83. Debug.LogError($"{name}事件不存在!");
  84. return;
  85. }
  86. }
  87. /// <summary>
  88. /// 呼叫事件
  89. /// </summary>
  90. /// <param name="command"></param>
  91. public void CallEvent(object command)
  92. {
  93. string name = command.GetType().Name + "_" + command;
  94. if (_events.ContainsKey(name))
  95. {
  96. (_events[name] as EventInfo).action?.Invoke();
  97. }
  98. else
  99. {
  100. Debug.LogError($"{name}事件不存在!");
  101. return;
  102. }
  103. }
  104. #endregion
  105. #region 有参事件
  106. private class EventInfo<T> : IEventInfo
  107. {
  108. public UnityAction<T> action;
  109. /// <summary>
  110. /// 构造函数添加事件
  111. /// </summary>
  112. /// <param name="call"></param>
  113. public EventInfo(UnityAction<T> call)
  114. {
  115. action += call;
  116. }
  117. }
  118. /// <summary>
  119. /// 添加事件监听
  120. /// </summary>
  121. /// <param name="command"></param>
  122. /// <param name="call"></param>
  123. public void AddEventListener<T>(object command, UnityAction<T> call)
  124. {
  125. string name = command.GetType().Name + "_" + command;
  126. if (_events.ContainsKey(name))
  127. {
  128. (_events[name] as EventInfo<T>).action += call;
  129. }
  130. else
  131. {
  132. _events.Add(name, new EventInfo<T>(call));
  133. }
  134. }
  135. /// <summary>
  136. /// 移除指定事件的指定监听
  137. /// </summary>
  138. /// <param name="command"></param>
  139. /// <param name="call"></param>
  140. public void RemoveEventListener<T>(object command, UnityAction<T> call)
  141. {
  142. string name = command.GetType().Name + "_" + command;
  143. if (_events.ContainsKey(name))
  144. {
  145. (_events[name] as EventInfo<T>).action -= call;
  146. }
  147. else
  148. {
  149. Debug.LogError($"{name}事件不存在!");
  150. return;
  151. }
  152. }
  153. /// <summary>
  154. /// 移除指定事件的所有监听
  155. /// </summary>
  156. /// <param name="command"></param>
  157. public void RemoveAllEventListeners<T>(object command)
  158. {
  159. string name = command.GetType().Name + "_" + command;
  160. if (_events.ContainsKey(name))
  161. {
  162. (_events[name] as EventInfo<T>).action = null;
  163. }
  164. else
  165. {
  166. Debug.LogError($"{name}事件不存在!");
  167. return;
  168. }
  169. }
  170. /// <summary>
  171. /// 呼叫事件
  172. /// </summary>
  173. /// <param name="command"></param>
  174. public void CallEvent<T>(object command, T value)
  175. {
  176. string name = command.GetType().Name + "_" + command;
  177. if (_events.ContainsKey(name))
  178. {
  179. (_events[name] as EventInfo<T>).action?.Invoke(value);
  180. }
  181. else
  182. {
  183. Debug.LogError($"{name}事件不存在!");
  184. return;
  185. }
  186. }
  187. #endregion
  188. }
  189. }
测试代码:
无参事件:

被观察类:

  1. public class Observer : MonoBehaviour
  2. {
  3. private void OnEnable()
  4. {
  5. EventCenterManager.Instance.AddEventListener("事件1", TestFunc);
  6. }
  7. private void OnDisable()
  8. {
  9. EventCenterManager.Instance.RemoveEventListener("事件1", TestFunc);
  10. }
  11. private void TestFunc()
  12. {
  13. Debug.Log("这是一个无参事件的测试方法");
  14. }
  15. }

 调用事件:

  1. public class Player : MonoBehaviour
  2. {
  3. // Start is called before the first frame update
  4. void Start()
  5. {
  6. EventCenterManager.Instance.CallEvent("事件1");
  7. }
  8. // Update is called once per frame
  9. void Update()
  10. {
  11. }
  12. }

有参事件:

被观察者类

  1. public class Observer : MonoBehaviour
  2. {
  3. private void OnEnable()
  4. {
  5. EventCenterManager.Instance.AddEventListener<bool>("事件2", TestFunc);
  6. }
  7. private void OnDisable()
  8. {
  9. EventCenterManager.Instance.RemoveEventListener<bool>("事件2", TestFunc);
  10. }
  11. private void TestFunc(bool value)
  12. {
  13. if (value)
  14. Debug.Log("这是一个真消息!");
  15. else
  16. Debug.Log("这是一个假消息!");
  17. }
  18. }

调用事件:

  1. public class Player : MonoBehaviour
  2. {
  3. // Start is called before the first frame update
  4. void Start()
  5. {
  6. EventCenterManager.Instance.CallEvent("事件2",true);
  7. }
  8. // Update is called once per frame
  9. void Update()
  10. {
  11. }
  12. }

 

         通过以上示例,你可以更好地理解在Unity中如何使用观察者模式来实现一种灵活且可维护的设计。

         希望这篇文章对你理解和应用观察者模式有所帮助。如果有任何疑问或建议,请在评论区留言。

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

闽ICP备14008679号