自定义unity事件系统

事件系统基础理论大家可以去自行搜索理解,这里暂且不谈(后续可能会讲),本章讲的是如何使用,个人观点:即使你不太理解事件系统,但如果你用的多了,后面理解时也会更轻松,会有一种原来这就是事件系统,我之前用到过的感慨。话不用多说,直接上干货:

1 定义事件:

    /// <summary>
    /// 事件字典
    /// </summary>
    private Dictionary<string, Action<object>> eventDictionary = new Dictionary<string, Action<object>>();
    //事件的队列
    private Queue<QueuedEvent> eventQueue = new Queue<QueuedEvent>();
public class QueuedEvent
{
    public string EventName { get; set; }
    public object Arg { get; set; }
}

eventDictionary 前面的string是你事件的名字,后面的是所需要执行的方法名。起到的作用大概相当于快递站,你得告诉工作人员你的名字或者你的取件码才能找到对应的快递。

至于队列部分,暂且不谈,在监听事件里会用到

2 监听事件:

    /// <summary>
    /// 监听事件
    /// </summary>
    /// <param name="eventName"></param>
    /// <param name="listener"></param>   
 public void StartListening(string eventName, Action<object> listener)
    {
        if (eventDictionary.ContainsKey(eventName))
        {
            eventDictionary[eventName] += listener;
        }
        else
        {
            eventDictionary.Add(eventName, listener);
        }

        // 如果队列中有待处理的事件,立即触发它们
        while (eventQueue.Count > 0 && eventQueue.Peek().EventName == eventName)
        {
            QueuedEvent queuedEvent = eventQueue.Dequeue();
            //发送事件
            TriggerEvent(queuedEvent.EventName, queuedEvent.Arg);
        }
    }

这段代码的话应该很容易理解,字典部分的事件如果有就替换,没有的话就添加。通俗一点呢就像你发了个快递,填的收件人是小红,小红就监听了这个事,这样到货了有短信通知自己(但代码世界里需要监听者自己去主动监听)下面的是个简单的例子

    void Start()
    {
        //监听事件
        EventManager.instance.StartListening("快递到了", SetInfo);
    }

    public void SetInfo(object obj)
    {
        //根据需要自定义的类型
        NextButtonInfo nextButtonInfo = obj as NextButtonInfo;
        //自己需要处理的逻辑
        ......
    }

while 循环里面的对列处理就是在所有的队列里查找,有的话移除队列然后发送事件

3 停止监听

    //停止监听
    public void StopListening(string eventName, Action<object> listener)
    {
        if (eventDictionary.ContainsKey(eventName))
        {
            eventDictionary[eventName] -= listener;
        }
    }

4 发送事件

    //发送事件
    public void TriggerEvent(string eventName, object arg = null)
    {
        Action<object> thisEvent;
        if (eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.Invoke(arg);
        }
        else
        {
            // 如果没有监听器注册这个事件,将它添加到队列中
            eventQueue.Enqueue(new QueuedEvent { EventName = eventName, Arg = arg });
        }
    }

这段代码呢着重解释下后面的else部分,之所以加这个东西是因为在实践过程中发现个问题,就是我这个事件还没监听呢,你就发送了,就像你发了个快递,已经到地方了,但还没通知收件人,你得找个地方帮他保存着,直到收件人来取货,也就是直到有人去监听事件,然后再去通知他,参数arg是发送事件时传的参数,可仿照下面的例子自定义

        NextButtonInfo nextButtonInfo = new NextButtonInfo ();
        nextButtonInfo .Title = "标题";
        nextButtonInfo .Info = " 内容";
        nextButtonInfo .action = () => 
        {
            //自己的方法
        };
        EventManager.instance.TriggerEvent("快递到了", summarizeInfo);

这里我把一个自定义的类NextButtonInfo 当做参数发送了出去,当有人监听到快递到了这个名字时,就会获得参数,当然,参数自定义,没有也行。

最后奉上全部代码,欢迎指正:

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

public class CustomEventManager : MonoBehaviour
{
    public static CustomEventManager instance;
    /// <summary>
    /// 事件字典
    /// </summary>
    private Dictionary<string, Action<object>> eventDictionary = new Dictionary<string, Action<object>>();
    //事件的队列
    private Queue<QueuedEvent> eventQueue = new Queue<QueuedEvent>();

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
    }
    /// <summary>
    /// 监听事件
    /// </summary>
    /// <param name="eventName"></param>
    /// <param name="listener"></param>
    public void StartListening(string eventName, Action<object> listener)
    {
        if (eventDictionary.ContainsKey(eventName))
        {
            eventDictionary[eventName] += listener;
        }
        else
        {
            eventDictionary.Add(eventName, listener);
        }

        // 如果队列中有待处理的事件,立即触发它们
        while (eventQueue.Count > 0 && eventQueue.Peek().EventName == eventName)
        {
            QueuedEvent queuedEvent = eventQueue.Dequeue();
            TriggerEvent(queuedEvent.EventName, queuedEvent.Arg);
        }
    }
    //停止监听
    public void StopListening(string eventName, Action<object> listener)
    {
        if (eventDictionary.ContainsKey(eventName))
        {
            eventDictionary[eventName] -= listener;
        }
    }
    //发送事件
    public void TriggerEvent(string eventName, object arg = null)
    {
        Action<object> thisEvent;
        if (eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.Invoke(arg);
        }
        else
        {
            // 如果没有监听器注册这个事件,将它添加到队列中
            eventQueue.Enqueue(new QueuedEvent { EventName = eventName, Arg = arg });
        }
    }
}
public class QueuedEvent
{
    public string EventName { get; set; }
    public object Arg { get; set; }
}

如果觉得还可以,点赞评论一下,大家一起共同进步。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity框架中的事件系统是一种消息传递机制,用于在各个组件之间发送和接收消息。它基于发布/订阅模式,其中一个组件发布事件,而其他组件通过订阅该事件来接收消息并做出相应的响应。 在Unity中,事件系统包括两种类型的事件Unity事件C#事件Unity事件是在Unity编辑器中定义的事件,可以在脚本中访问。C#事件是由C#编写的自定义事件。 使用Unity事件系统的步骤包括: 1. 定义事件:创建一个事件类来定义事件的名称和参数。 2. 注册事件:在需要接收该事件的组件中注册该事件。 3. 发布事件:当某个条件满足时,发布该事件。 4. 响应事件:在接收到事件时,执行相应的操作。 以下是一个示例代码,展示如何在Unity中使用事件系统: ``` //定义事件类 public class MyEvent : UnityEvent<int, string> {} //注册事件 public MyEvent myEvent = new MyEvent(); void Start() { myEvent.AddListener(MyEventHandler); } //发布事件 if (condition) { myEvent.Invoke(1, "message"); } //响应事件 void MyEventHandler(int value, string message) { Debug.Log(message + " " + value); } ``` 在这个示例中,我们定义了一个名为MyEvent的事件类,该事件有两个参数:int和string类型。然后,我们在Start方法中注册了该事件,并在某个条件得到满足时发布了该事件。最后,我们在MyEventHandler方法中响应了该事件,输出了传递的参数。 总的来说,Unity框架中的事件系统是一种非常有用的消息传递机制,可以帮助开发者优化代码结构,提高代码的可读性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值