1, 编写 EventManager 类
一个事件管理类通过包括三个功能, 订阅, 发布消息, 取消订阅, 对应到代码中, 也是就三个方法: AddEvent,DispatchEvent,RemoveEvent, 还有一个字典 List, 对订阅事件做管理, 实现如下:
- /**
- * UnityVersion: 2018.3.1f1
- * FileName: EventManager.cs
- * Author: TYQ
- * CreateTime: 2019/04/04 15:49:53
- * Description: 自定义的事件派发类
- */
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class EventManager
- {
- /// <summary>
- /// 带返回参数的回调列表, 参数类型为 T, 支持一对多
- /// </summary>
- public static Dictionary<string, List<Delegate>> events = new Dictionary<string, List<Delegate>>();
- /// <summary>
- /// 注册事件, 1 个返回参数
- /// </summary>
- /// <param name="eventName"></param>
- /// <param name="callback"></param>
- public static void AddEvent<T> (string eventName, Action<T> callback)
- {
- List<Delegate> actions = null;
- //eventName 已存在
- if (events.TryGetValue(eventName, out actions))
- {
- actions.Add(callback);
- }
- //eventName 不存在
- else
- {
- actions = new List<Delegate>();
- actions.Add(callback);
- events.Add(eventName ,actions);
- }
- }
- /// <summary>
- /// 注册事件, 不带返回参数
- /// </summary>
- /// <param name="eventName"></param>
- /// <param name="callback"></param>
- public static void AddEvent(string eventName, Action callback)
- {
- List<Delegate> actions = null;
- //eventName 已存在
- if (events.TryGetValue(eventName, out actions))
- {
- actions.Add(callback);
- }
- //eventName 不存在
- else
- {
- actions = new List<Delegate>();
- actions.Add(callback);
- events.Add(eventName, actions);
- }
- }
- /// <summary>
- /// 移除事件
- /// </summary>
- /// <param name="eventName"></param>
- /// <param name="callback"></param>
- public static void RemoveEvent<T>(string eventName, Action<T> callback)
- {
- List<Delegate> actions = null;
- if (events.TryGetValue(eventName, out actions))
- {
- actions.Remove(callback);
- if (actions.Count == 0)
- {
- events.Remove(eventName);
- }
- }
- }
- /// <summary>
- /// 移除全部事件
- /// </summary>
- public static void RemoveAllEvents ()
- {
- events.Clear();
- }
- /// <summary>
- /// 派发事件
- /// </summary>
- /// <param name="eventName"></param>
- /// <param name="arg"></param>
- public static void DispatchEvent<T>(string eventName, T arg)
- {
- List<Delegate> actions = null;
- if (events.ContainsKey(eventName))
- {
- events.TryGetValue(eventName, out actions);
- foreach (var act in actions)
- {
- act.DynamicInvoke(arg);
- }
- }
- }
- /// <summary>
- /// 派发事件, 不带参数
- /// </summary>
- /// <param name="eventName"></param>
- /// <param name="arg"></param>
- public static void DispatchEvent(string eventName)
- {
- List<Delegate> actions = null;
- if (events.ContainsKey(eventName))
- {
- events.TryGetValue(eventName, out actions);
- foreach (var act in actions)
- {
- act.DynamicInvoke();
- }
- }
- }
- }
EventManager.cs
2, 测试事件类
2.1, 先制作测试界面, 包括两个接收 (订阅) 消息的 Text 组件, 以及一个发布消息的 Slider 组件, 层次结构见下图:
预期效果: 拖动 Slider,Slider 的值会同步显示到两个用于接收的 Text 组件上.
2.2, 编写测试类
先写一个发布消息的类, 在 Slider 的 onValueChanged 事件中执行发布操作, 如下
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
- public class Sender : MonoBehaviour
- {
- public Slider slider = null;
- private void Awake()
- {
- slider.onValueChanged.AddListener(delegate (float value) {
- Debug.LogFormat("slider:{0}", value);
- // 有参分发
- EventManager.DispatchEvent<float>("NumberEvent", value);
- // 无参分发
- EventManager.DispatchEvent("NumberEventNoParam");
- });
- }
- }
Sender.cs
再写一下接收消息的类,, 如下
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
- public class Receiver : MonoBehaviour
- {
- public Text receiveText1 = null;
- public Text receiveText2 = null;
- private void Awake()
- {
- // 带参数回调
- // 注册方法 1
- EventManager.AddEvent<float>("NumberEvent", OnNumberChangeEventHandler);
- // 注册方法 2
- EventManager.AddEvent("NumberEvent", delegate (float arg) {
- receiveText2.text = (Convert.ToInt32(arg)).ToString();
- });
- // 无参回调
- EventManager.AddEvent("NumberEventNoParam", delegate () {
- Debug.Log("无参回调");
- });
- }
- /// <summary>
- /// 事件处理方法
- /// </summary>
- /// <param name="arg"></param>
- private void OnNumberChangeEventHandler (float arg)
- {
- receiveText1.text = (Convert.ToInt32(arg)).ToString();
- }
- }
Receiver.cs
2.3, 运行
运行结果如下图:
可以看到, Slider 值的改变会立马同步到接收端 Text 中, 实现了预期的功能.
来源: https://www.cnblogs.com/imteach/p/10679239.html