基于Unity的事件管理者


个人使用的事件管理者,用于项目中的事件分发,以增加代码的灵活性。

事件

由于本人习惯,本着“多一事不如少一事“”的原则,使用的是程序库中自带的事件EventHandler

using System.Runtime.InteropServices;

namespace System
{
    [ComVisible(true)]
    public delegate void EventHandler(object sender, EventArgs e);
}

其中,参数EventArgs类,也是程序库中自带的:

using System.Runtime.InteropServices;

namespace System
{
    [ComVisible(true)]
    public class EventArgs
    {
        public static readonly EventArgs Empty;

        public EventArgs();
    }
}

管理者

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

/// <summary>
/// 事件管理者
/// </summary>
public class EventManager : Singleton<EventManager>
{
    Dictionary<GameObject, Dictionary<Type, EventHandler>> m_dic = new Dictionary<GameObject, Dictionary<Type, EventHandler>>();

    /// <summary>
    /// 增加事件
    /// </summary>
    /// <typeparam name="T">事件的参数类</typeparam>
    /// <param name="owner">拥有对象</param>
    /// <param name="eh">事件</param>
    public void AddEvent<T>(GameObject owner, EventHandler eh) where T : EventArgs
    {
        if (!m_dic.ContainsKey(owner))
        {
            m_dic[owner] = new Dictionary<Type, EventHandler>();
        }
        Type type = typeof(T);
        if (m_dic[owner].ContainsKey(type))
        {
            m_dic[owner][type] += eh;
        }
        else
        {
            m_dic[owner][type] = eh;
        }
    }

    /// <summary>
    /// 触发事件
    /// </summary>
    /// <typeparam name="T">事件的参数类</typeparam>
    /// <param name="owner">拥有对象</param>
    /// <param name="sender">事件的参数</param>
    /// <param name="t">事件的参数</param>
    public void TriggerEvent<T>(GameObject owner, object sender, T t) where T : EventArgs
    {
        if (m_dic.ContainsKey(owner))
        {
            Type type = typeof(T);
            if (m_dic[owner].ContainsKey(type))
            {
                m_dic[owner][type].Invoke(sender, t);
            }
        }
    }

    /// <summary>
    /// 移除事件
    /// </summary>
    /// <typeparam name="T">事件的参数类</typeparam>
    /// <param name="owner">拥有对象</param>
    /// <param name="eh">事件</param>
    public void RemoveEvent<T>(GameObject owner, EventHandler eh) where T : EventArgs
    {
        if (m_dic.ContainsKey(owner))
        {
            Type type = typeof(T);
            if (m_dic[owner].ContainsKey(type))
            {
                m_dic[owner][type] -= eh;
            }
        }
    }
}

该类为单例,继承的便是我自己编写的一个单例父类,之前有篇专门记录的文章:可点击查看相关文章
在代码中,有一个两重字典,用于准确确定到我们所要用到的事件。第一重为GameObject类型,是场景中的一个物体;第二重为一个衍生自EventArgs类型的类的类型。

使用

使用这个事件管理者时,先写一个与事件EventHandler结构一样的一个函数:

public void TestEvent(object sender, EventArgs e)
{

}

然后再创建一个衍生自EventArgs类型的类:

public class TestEventArgs : EventArgs
{

}

然后将函数中所要真正用到的参数,以字段的形式创建于该类中。再只需要在函数中,将EventArgs类的参数转换成对应类型(如例:TestEventArgs)

public void TestEvent(object sender, EventArgs e)
{
	TestEventArgs tea=(TestEventArgs)e;
}

便可以获取到真正传入的所需要的参数了。在其之后便可编写执行逻辑。
使用事件前先将其添加入事件管理者:

EventManager.GetInstance().AddEvent<TestEventArgs>(gameObject, TestEvent);

触发事件时:

EventManager.GetInstance().TriggerEvent(gameObject, 0new TestEventArgs());

其中的数字0,便是函数的第1个object类型的参数,如有需要,可自行更改。
最后不需要其事件时,可以将其在管理者中删除:

EventManager.GetInstance().RemoveEvent<TestEventArgs>(gameObject, TestEvent);

简化扩展

UnityAction

Unity中给出了一个UnityEngine.Events命名空间,里面有2个已经定义好的事件:
一个是无参的事件;

namespace UnityEngine.Events
{
    //
    // 摘要:
    //     Zero argument delegate used by UnityEvents.
    public delegate void UnityAction();
}

另一个是有一个参数的事件。

namespace UnityEngine.Events
{
    public delegate void UnityAction<T0>(T0 arg0);
}

UnityEvent

然后,还有两个根据上面两种事件封装好的事件类,分别是:

namespace UnityEngine.Events
{
    //
    // 摘要:
    //     A zero argument persistent callback that can be saved with the Scene.
    public class UnityEvent : UnityEventBase
    {
        //
        // 摘要:
        //     Constructor.
        [RequiredByNativeCode]
        public UnityEvent();

        //
        // 摘要:
        //     Add a non persistent listener to the UnityEvent.
        //
        // 参数:
        //   call:
        //     Callback function.
        public void AddListener(UnityAction call);
        //
        // 摘要:
        //     Invoke all registered callbacks (runtime and persistent).
        public void Invoke();
        //
        // 摘要:
        //     Remove a non persistent listener from the UnityEvent.
        //
        // 参数:
        //   call:
        //     Callback function.
        public void RemoveListener(UnityAction call);
        protected override MethodInfo FindMethod_Impl(string name, object targetObj);
    }
}
namespace UnityEngine.Events
{
    //
    // 摘要:
    //     One argument version of UnityEvent.
    public abstract class UnityEvent<T0> : UnityEventBase
    {
        [RequiredByNativeCode]
        public UnityEvent();

        public void AddListener(UnityAction<T0> call);
        public void Invoke(T0 arg0);
        public void RemoveListener(UnityAction<T0> call);
        protected override MethodInfo FindMethod_Impl(string name, object targetObj);
    }
}

UnityEventManager

结合上面的事件管理者,便归纳总结了下面的脚本:

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

public class UnityEventManager : Singleton<UnityEventManager>
{
    private UnityEventManager()
    {
        m_UnityEventDic = new Dictionary<Type, UnityEventArgs>();
    }

    private Dictionary<Type, UnityEventArgs> m_UnityEventDic;

    /// <summary>
    /// 增加事件
    /// </summary>
    /// <typeparam name="T">事件的参数类</typeparam>
    /// <param name="uEvent">事件</param>
    public void AddEvent<T>(UnityAction<EventArgs> uEvent) where T : EventArgs
    {
        Type type = typeof(T);
        if (m_UnityEventDic.ContainsKey(type))
        {
            m_UnityEventDic[type].AddListener(uEvent);
        }
        else
        {
            m_UnityEventDic[type] = new UnityEventArgs();
            m_UnityEventDic[type].AddListener(uEvent);
        }
    }
    /// <summary>
    /// 触发事件
    /// </summary>
    /// <typeparam name="T">事件的参数类</typeparam>
    /// <param name="t">事件的参数</param>
    public void TriggerEvent<T>(T t) where T : EventArgs
    {
        Type type = typeof(T);
        if (m_UnityEventDic.ContainsKey(type))
        {
            m_UnityEventDic[type].Invoke(t);
        }
    }
    /// <summary>
    /// 移除事件
    /// </summary>
    /// <typeparam name="T">事件的参数类</typeparam>
    /// <param name="uEvent">事件</param>
    public void RemoveEvent<T>(UnityAction<EventArgs> uEvent) where T : EventArgs
    {
        Type type = typeof(T);
        if (m_UnityEventDic.ContainsKey(type))
        {
            m_UnityEventDic[type].RemoveListener(uEvent);
        }
    }

    private class UnityEventArgs : UnityEvent<EventArgs>
    {

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Unity中,我们可以使用C#中的事件Event)和委托(Delegate)机制来实现一个基于观察者的全局事件系统。 首先,我们可以定义一个委托类型,用于定义事件的回调函数: ```csharp public delegate void EventHandler(); ``` 然后,我们可以定义一个静态类,用于管理所有事件: ```csharp public static class EventManager { private static Dictionary<string, EventHandler> eventDictionary = new Dictionary<string, EventHandler>(); public static void AddHandler(string eventName, EventHandler handler) { if (eventDictionary.ContainsKey(eventName)) { eventDictionary[eventName] += handler; } else { eventDictionary[eventName] = handler; } } public static void RemoveHandler(string eventName, EventHandler handler) { if (eventDictionary.ContainsKey(eventName)) { eventDictionary[eventName] -= handler; } } public static void TriggerEvent(string eventName) { if (eventDictionary.ContainsKey(eventName)) { eventDictionary[eventName]?.Invoke(); } } } ``` 在这个静态类中,我们使用一个Dictionary来存储所有事件的回调函数,使用AddHandler方法和RemoveHandler方法来添加和移除事件的回调函数,使用TriggerEvent方法来触发事件。 例如,我们可以定义一个名为"PlayerDead"的事件: ```csharp public class Player : MonoBehaviour { void Die() { EventManager.TriggerEvent("PlayerDead"); } } ``` 然后,在其他脚本中,我们可以使用AddHandler方法和RemoveHandler方法来订阅和取消订阅该事件: ```csharp public class GameManager : MonoBehaviour { void OnEnable() { EventManager.AddHandler("PlayerDead", OnPlayerDead); } void OnDisable() { EventManager.RemoveHandler("PlayerDead", OnPlayerDead); } void OnPlayerDead() { Debug.Log("Game Over"); } } ``` 这样,当玩家死亡时,所有订阅了"PlayerDead"事件的脚本都会收到通知,并执行相应的操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天富儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值