Unity组件开发--事件管理器

1.创建单例脚本:SingletonBase

cs 复制代码
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

cs 复制代码
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;
        else
            handlerDic.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_EDITOR
        if (handlerDic.ContainsKey(eventName))
            handlerDic[eventName]?.Invoke(sender, args);
#else
        try {
                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

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class EventName
{
    public const string SocketOpen = nameof(SocketOpen);
    
    
}

4.事件回调参数脚本:CustomEventArgs

cs 复制代码
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.如何使用:

cs 复制代码
EventManager.Instance.AddListener(EventName.OnSceneLoaded, (s, e) => { //场景未加载之前,不让玩家操作
    enabled = true;
});
cs 复制代码
EventManager.Instance.AddListener(EventName.ChangeAngle, changeAngle);
cs 复制代码
this.TriggerEvent(EventName.ChangeAngle, new AngleChangeEventArgs { angleIndex = 3 });
相关推荐
万兴丶41 分钟前
Unity 适用于单机游戏的红点系统(前缀树 | 数据结构 | 设计模式 | 算法 | 含源码)
数据结构·unity·设计模式·c#
程序猿多布2 小时前
C#设计模式 学习笔记
设计模式·c#
软件黑马王子8 小时前
Unity游戏制作中的C#基础(5)条件语句和循环语句知识点全解析
游戏·unity·c#
shepherd枸杞泡茶8 小时前
第3章 3.3日志 .NET Core日志 NLog使用教程
c#·asp.net·.net·.netcore
龚子亦13 小时前
Unity结合Vuforia虚拟按键实现AR机械仿真动画效果
unity·游戏引擎·ar·数字孪生·虚拟仿真
Aimeast15 小时前
关于选择最佳.NET Core SSH服务器库的全面分析
c#·ssh
蒋劲豪15 小时前
WPF项目暴露WebApi接口;WinForm项目暴露WebApi接口;C#项目暴露WebApi接口;
开发语言·c#·wpf
code bean16 小时前
【C# 数据结构】队列 FIFO
开发语言·数据结构·c#
时光追逐者19 小时前
推荐几款开源免费的 .NET MAUI 组件库
microsoft·开源·c#·.net·.net core·maui
软件黑马王子20 小时前
C#初级教程(1)——C# 与.NET 框架:探索微软平台编程的强大组合
开发语言·c#