MVE方法中EventManager的多种实现办法(Unity c#)

EventManager (UnityEvent)

好处:一个UnityEvent可以便捷添加与删除多个函数

坏处:不正确地被外部调用,外部调用一次,相应的函数可能会触发两次

多次触发的原因与UnityAction有关,UnityEvent本身被外部调用的时候只会触发一次,但是因为UnityEvent本身由UnityAction组成,所以即使UnityEvent本身只被调用了一次,UnityEvent中的UnityAction被调用多次,相应的函数也会被调用多次

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class EventManager 
{
    private static EventManager _instance = null;
    public static EventManager GetInstance
    {
        get
        {
            if (_instance == null)
                _instance = new EventManager();
            return _instance;
        }
    }

    private Dictionary<string, UnityEvent> eventData = new Dictionary<string, UnityEvent>();
    private Dictionary<string, UnityEvent<float[]>> eventSetData = new Dictionary<string, UnityEvent<float[]>>();
    
    /// <summary>
    /// 提供给外部使用的添加监听升级事件
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void AddListener(string eventName, UnityAction function)
    {
        if (!eventData.ContainsKey(eventName))
        {
           UnityEvent @event = new UnityEvent();
            @event.AddListener(function);
            eventData.Add(eventName, @event);
            //Debug.Log("AddListener" + eventName);
        }            
        if (eventData.ContainsKey(eventName) && !eventData[eventName].Equals(function))
        {
            eventData[eventName].AddListener(function);
            //Debug.Log("AddListener" + eventName);
        }
    }

    /// <summary>
    /// 提供给外部使用的移除升级事件监听
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void RemoveListener(string eventName, UnityAction function)
    {
        if (eventData.ContainsKey(eventName) && eventData[eventName].Equals(function))
        {
            eventData[eventName].RemoveListener(function);
        }
        if (eventData[eventName] == null)
        {
            eventData.Remove(eventName);
        }
    }
    /// <summary>
    /// 提供给外部使用的添加监听改变数值的事件
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void AddSetListener(string eventName, UnityAction<int[]> function)
    {
        if (!eventSetData.ContainsKey(eventName))
        {
            UnityEvent<float[]> @event = new UnityEvent<float[]>();
            @event.AddListener(function);
            eventSetData.Add(eventName, @event);
            //Debug.Log("AddSetListener" + eventName);
        }
        if (eventSetData.ContainsKey(eventName) && !eventSetData[eventName].Equals(function))
        {
            eventSetData[eventName].AddListener(function);
            //Debug.Log("AddSetListener" + eventName);
        }

    }
    /// <summary>
    /// 提供给外部使用的移除升级事件监听
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void RemoveSetListener(string eventName, UnityAction<int[]> function)
    {
        if (eventSetData.ContainsKey(eventName) &&
            eventSetData[eventName].Equals(function))
            eventSetData[eventName].RemoveListener(function);
        if (eventSetData[eventName] == null)
        {
            eventSetData.Remove(eventName);
        }
    }
    /// <summary>
    /// 触发事件
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    public void TriggerEvent(string eventName)
    {
        if (eventData[eventName] != null)
            eventData[eventName].Invoke();
    }

    /// <summary>
    /// 触发事件
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    public void TriggerSetEvent(string eventName, int[] model)
    {
        if (eventSetData[eventName] != null)
            eventSetData[eventName].Invoke(model);
    }
    public void ClearEvent(string name)
    {
        if (eventData.ContainsKey(name))
        {
            eventData.Remove(name);
        }
        if (eventSetData.ContainsKey(name))
        {
            eventSetData.Remove(name);
        }
    }

    public void ClearAllEvents()
    {
        if (eventData.Count != 0)
        {
            eventData.Clear();
        }
        if (eventSetData.Count != 0)
        {
            eventSetData.Clear();
        }
    }
}

EventManager (Delegate)

好处:能够正确地被外部调用,外部调用一次,相应的函数只会触发一次

坏处:如果Remove函数使用的是只删除该key值中一个事件的版本,很难在脚本生命周期的更替中妥善管理非静态方法(如果Remove函数使用的是删除该key值中所有函数的版本,则可以在脚本生命周期中较好的控制所有的事件 前提是一个事件对应一个key)

(不过如果能够了解每个添加进来的监听事件,在监听事件所在脚本生命周期结束前Remove并且保证不需要这个事件有跨生命周期的部分的话,还是可以使用的)

*当然,使用UnityEvent实现的Remove方法(只删除一个key下的某一个监听事件)也会有无法准确通过key值进行管理的问题

*因为TriggerEvent与ClearEvent的方式与UnityEvent相同,就不在此赘述了

delegate void DeleFunc();
delegate void DeleFuncFloat(float[] f);
private Dictionary<string, DeleFunc> eventData = new Dictionary<string, DeleFunc>();
private Dictionary<string, DeleFuncFloat> eventSetData = new Dictionary<string, DeleFuncFloat>();
/// <summary>
    /// 提供给外部使用的添加监听事件
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void AddSetListener(string eventName, UnityAction<float[]> function)
    {
        DeleFuncFloat deleFunc = new DeleFuncFloat(function);
        if (!eventSetData.ContainsKey(eventName))
        {
            eventSetData.Add(eventName, deleFunc);
            //Debug.Log("AddSetListener" + eventName);
        }
        if (eventSetData.ContainsKey(eventName) && !eventSetData[eventName].Equals(deleFunc))
        {
            eventSetData[eventName] += deleFunc;
            //Debug.Log("AddSetListener" + eventName);
        }
    }
    /// <summary>
    /// 提供给外部使用的移除事件监听
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void RemoveSetListener(string eventName, UnityAction<float[]> function)
    {
        if (!eventSetData.ContainsKey(eventName)) return;
#region 移除该key值下某个具体的监听事件,在脚本生命周期的改变中可能会出错(无法定位某一脚本的某一事件)
        //foreach(DeleFuncFloat deleFuncFloat in eventSetData[eventName].GetInvocationList())
        //{
        //    if (deleFuncFloat.Equals(function))
        //    {
        //        eventSetData[eventName] -= deleFuncFloat;
        //        if (eventSetData[eventName] == null)
        //        {
        //            eventSetData.Remove(eventName);
        //            Debug.Log("RemoveAll" + eventName);
        //        }                
        //    }
        //}
        #endregion

        #region 移除改key值下的所有事件,可通过key值准确的跨生命周期管理各个事件,推荐
        //Debug.Log("Remove" + eventName);
        {
            eventSetData.Remove(eventName);
            Debug.Log("RemoveAll" + eventName);
        }
        #endregion

    }

    /// <summary>
    /// 提供给外部使用的添加监听事件
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void AddListener(string eventName, UnityAction function)
    {
        DeleFunc deleFunc = new DeleFunc(function);
        if (!eventData.ContainsKey(eventName))
        {
            eventData.Add(eventName, deleFunc);
            //Debug.Log("AddListener" + eventName);
        }
        if (eventData.ContainsKey(eventName) && !eventData[eventName].Equals(deleFunc))
        {
            eventData[eventName] += deleFunc;
            //Debug.Log("AddListener" + eventName);
        }
    }

    /// <summary>
    /// 提供给外部使用的移除事件监听
    /// </summary>
    /// <param name="eventName">监听的事件名字</param>
    /// <param name="function">监听的函数</param>
    public void RemoveListener(string eventName, UnityAction function)
    {
        if (!eventData.ContainsKey(eventName)) return;
        #region 移除该key值下某个具体事件,在脚本生命周期的改变中可能会出错(无法定位某一脚本的某一事件)
        //foreach(DeleFunc deleFunc in eventData[eventName].GetInvocationList())
        //{
        //    if (deleFunc.Equals(function))
        //    {
        //        eventData[eventName] -= deleFunc;
        //        if (eventData[eventName] == null)
        //        {
        //            eventData.Remove(eventName);
        //            Debug.Log("RemoveAll" + eventName);
        //        }                
        //    }
        //}
        #endregion

        #region 移除改key值下的所有事件,可通过key值准确的跨生命周期管理各个事件,推荐
        //Debug.Log("Remove" + eventName);
        {
            eventData.Remove(eventName);
            Debug.Log("RemoveAll" + eventName);
        }
        #endregion
    }

相关文档

七.MV"X"之MVE - 知乎

本文的MVE方法参考了这篇文章,不了解MVE的朋友可以看看这篇了解一下。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值