1.创建单例脚本:SingletonBase
public class SingletonBase<T> where T : new()
{private static T instance;// 多线程安全机制private static readonly object locker = new object();public static T Instance{get{if (instance == null){//lock写第一个if里是因为只有该类的实例还没创建时,才需要加锁,这样可以节省性能lock (locker){if (instance == null)instance = new T();}}return instance;}}
}
2.事件管理器单例脚本:EventManager
using System.Collections.Generic;
using System;
using System.Diagnostics;
using UnityEngine.Device;
/// <summary>
/// 便于触发事件的扩展类
/// </summary>
public static class EventTriggerExt
{/// <summary>/// 触发事件(无参数)/// </summary>/// <param name="sender">触发源</param>/// <param name="eventName">事件名</param>public static void TriggerEvent(this object sender, string eventName){EventManager.Instance.TriggerEvent(eventName, sender,null);}/// <summary>/// 触发事件(有参数)/// </summary>/// <param name="sender">触发源</param>/// <param name="eventName">事件名</param>/// <param name="args">事件参数</param>public static void TriggerEvent(this object sender, string eventName, EventArgs args){EventManager.Instance.TriggerEvent(eventName, sender, args);}}
/// <summary>
/// 事件管理器
/// </summary>
public class EventManager : SingletonBase<EventManager>
{private Dictionary<string, EventHandler> handlerDic = new Dictionary<string, EventHandler>();/// <summary>/// 添加一个事件的监听者/// </summary>/// <param name="eventName">事件名</param>/// <param name="handler">事件处理函数</param>public void AddListener(string eventName, EventHandler handler){if (handlerDic.ContainsKey(eventName))handlerDic[eventName] += handler;elsehandlerDic.Add(eventName, handler);}/// <summary>/// 移除一个事件的监听者/// </summary>/// <param name="eventName">事件名</param>/// <param name="handler">事件处理函数</param>public void RemoveListener(string eventName, EventHandler handler){if (handlerDic.ContainsKey(eventName))handlerDic[eventName] -= handler;}/// <summary>/// 触发事件 无senser/// </summary>/// <param name="eventName"></param>/// <param name="args"></param>public void TriggerEvent(string eventName, EventArgs args){TriggerEvent(eventName, null, args);}/// <summary>/// 触发事件(有参数)/// </summary>/// <param name="eventName">事件名</param>/// <param name="sender">触发源</param>/// <param name="args">事件参数</param>public void TriggerEvent(string eventName, object sender, EventArgs args){if (!Application.isPlaying) {return;}UnityEngine.Debug.Log("TriggerEvent:"+ eventName);
#if UNITY_EDITORif (handlerDic.ContainsKey(eventName))handlerDic[eventName]?.Invoke(sender, args);
#elsetry {if (handlerDic.ContainsKey(eventName))handlerDic[eventName]?.Invoke(sender, args);}catch (Exception e) {UnityEngine.Debug.LogError(e.Message + "\n" + e.StackTrace);}
#endif}/// <summary>/// 清空所有事件/// </summary>public void Clear(){handlerDic.Clear();}
}
3.事件名称定义脚本:EventName
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public static class EventName
{public const string SocketOpen = nameof(SocketOpen);}
4.事件回调参数脚本:CustomEventArgs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UTNET;
using agora_gaming_rtc;
using UnityEngine.Events;
//将所有的事件参数类统一写在这个脚本public class LightColorChangeEventArgs : EventArgs
{public float red;public float green;public float blue;
}
5.如何使用:
EventManager.Instance.AddListener(EventName.OnSceneLoaded, (s, e) => { //场景未加载之前,不让玩家操作enabled = true;
});
EventManager.Instance.AddListener(EventName.ChangeAngle, changeAngle);
this.TriggerEvent(EventName.ChangeAngle, new AngleChangeEventArgs { angleIndex = 3 });