Unity实用框架(三)事件系统

Unity实用框架(三)事件系统

在Unity提供的事件注册基础上,实现一个更加灵活的事件系统。

Event

首先,为所有可能的事件定义一个公用的事件基类。该基类包含:事件的发起者(UNITY对象)、要求响应的方式(同步或异步)以及事件是否在处理后销毁。

public abstract class Event : IDisposable
{
    private GameObject publisher;
    private bool responce;
    private bool disposeAfterUsed;
}

那么,任何类型只要继承自Event,就可以作为一个事件在MessageSystem里面进行发布和监听。当然,如果每种事件都单独写一个类型,或许会使得类的数量过多,可以将同模块下的所有事件封装到一个Event的子类当中,再通过字符串或枚举等方式进行二次查找。比如如下方式:

public class NetWorkConnectionEvent : Event{
    ...
    enum Type{
        EventType1,
        EventType2,
        ...
    } 
    ...
}

如果使用这种写法,MessageSystem会更加复杂,为了方便,我们在下面假设所有的事件都继承自Event,每个Event代表且仅代表一个事件。

IEventListener

一个类型实现该接口,以表明自己是一个可以监听事件的类型。该接口需要实现监听函数

public interface IEventListener
{
    bool OnEvent(Event e);
}

MessageSystem

Subscribe/Unsubscribe

一个基础的事件系统应当至少能够实现事件的发布和订阅功能。首先,我们定义以下几个列表,来储存订阅者信息。

private Dictionary<Event, List<IEventListener>> Listeners;
private List<KeyValuePair<Event, IEventListener> subscribeRequests;
private List<KeyValuePair<Event, IEventListener> > unsubscribeRequests

字典Listeners储存了注册到某个事件的所有监听者,用法很清晰,那么下面两个列表用处何在呢?由于场景中随时都会存在动态地事件注册和取消注册,因此,下面两个变量用于在MessageSystem.Update函数中,将新注册的Listener更新到Listener中,或从Listener中移除。当Listener的某个Key对应的Value为空时(即某个Event未被任何监听者注册),那么这个KEY将会被移除,相应地,而若新注册的监听者发现Listener中没有对应的Event,也会新增一个对应的Key。用这种动态的注册方法,可以避免事件系统中出现大量的无用注册信息以提高运行效率。

在Subscribe/Unsubscribe中,将需要Subscribe/Unsubscribe的监听者加入对应的列表。

subscribeRequests.Add(new KeyValuePair<Event, IEventListener>(e, listener);
unsubscribeRequests.Add(new KeyValuePair<Event, IEventListener>(e, listener);

在Update中,将它们更新到Listener:

foreach (var subReq in subscribeRequests)
{
    List<IEventListener> callbacks = null;
    if (Listeners.TryGetValue(subReq.Key, out callbacks))
    {
        callbacks.Add(subReq.Value);
    }
    else
    {
        callbacks = new List<IEventListener>();
        callbacks.Add(subReq.Value);
        listeners.Add(subReq.Key, callbacks);
    }
}
subscribeRequests.Clear();

var infoToUnsubscribe = new SubscribeCallbackInfo(null, false);
foreach (var unsubReq in unsubscribeRequests)
{
    List<IEventListener> callbacks = null;
    if (Listeners.TryGetValue(unsubReq.Key, out callbacks))
    {
        if (callbacks.Remove(unsubReq.Value))
        {
            if (callbacks.Count == 0)
            {
                subscribeCallbacks.Remove(unsubReq.Key);
            }
        }
    }
}
unsubscribeRequests.Clear();
Publish

现在已经有了订阅信息,需要一个Publish函数来发布事件。

public void Publish(Event e);

发布者决定了事件的处理方式(同步-异步)以及销毁方式,对于异步调用,直接循环遍历Listener中对应的List即可:

List<IEventListener> listeners;
if(Listeners.TryGetValue(e, out listeners)){
    for(listener in listeners){
        listener.OnEvent(e);
    }
}

对于同步调用,用StartCoroutine协程代替直接调用:

StartCoroutine(listener.OnEvent(e));

有些时候,我们只需要事件被任何一个监听者处理掉就够了,而不需要所有监听者都去处理它,因此,发布者可以将Event.disposeAfterUsed置为true,在publish中,只要某一个监听者处理了事件,那么销毁该事件,不需要将其向下传递。

List<IEventListener> listeners;
if(Listeners.TryGetValue(e, out listeners)){
    for(listener in listeners){
        if(listener.OnEvent(e)){
            e.dispose();
            break;
        }
    }
}

更新时间:2022.7.17

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值