用Unity作个游戏(二) - 事件系统

本文首发自inspoy的杂七杂八 | 菜鸡inspoy的学习记录php

前言

以前一直在用cocos2d-x用c++写代码嘛,因此为了开发方便本身设计了一套事件系统,如今转到unity用c#了,就很天然地把以前那套东西搬过来用了XD
C#自带的event其实就彻底能够用,不过功能略显简陋,Unity自带的EventSystem感受太复杂了,并且我又不太喜欢去操做editor,因此我仍是决定本身造轮子,弄一个最适合本身的事件机制html

设计

事件机制基于观察者模式,事件订阅者向某个事件发布者订阅事件,绑定回调函数,事件发布者发布事件时会通知全部订阅者,按订阅顺序依次调用他们预留的回调函数
三个类,SFEvent(SF是前缀,啥意思你们也不用在乎233),SFEventDataSFEventDispatcherc++

做用
SFEvent 事件类
SFEventData 事件所包含的数据
SFEventDispatcher 事件发布者

SFEvent

其中,事件类SFEvent包含类型,事件数据SFEventData,以及发布者
不一样事件的数据可能须要不一样的数据结构,因此咱们抽象出一层接口ISFEventData,实际使用的数据结构均继承这个接口便可
下面贴出部分代码(不完整,完整代码见本文末尾)git

public class SFEvent
{
    public string eventType; // 事件类型

    public ISFEventData data; // 事件包含的自定义数据

    public object target; // 事件发送者

    // 如下是事件枚举
    public const string EVENT_TEST = "EVENT_TEST";
};

public interface ISFEventData
{
};复制代码

SFEventData

全部事件数据的数据结构均继承了ISFEventData这个空接口,这样一来不一样的事件就能够定制本身须要的事件数据结构了,若是时间数据很是简单好比只有一个数字,我这里也准备了一个通用的数据结构:github

public class SFSimpleEventData : ISFEventData
{
    public object objVal = null;
    public int intVal = 0;
    public float floatVal = 0;
    public string strVal = "";
}复制代码

SFEventDispatcher

这个事件系统的核心部分,负责分发事件,管理订阅
以前用cocos的时候习惯使用多继承的方式来把dispatcher的功能加到一个类上,不过如今C#不支持多继承了,因而就只能使用组合的方式,在类中储存一个dispatcher类的实例来实现相似的效果。写法会从this->dispatchEvent(e);变成this.dispatcher.dispatchEvent(e);
使用C#的委托来实现订阅,订阅者传递这个委托类型的回调函数给发布者便可:c#

public delegate void SFListenerSelector(SFEvent e);复制代码

使用一个字典来管理不一样的事件所各自对应的订阅者数据结构

Dictionary<string, List<SFListenerSelector> > m_dictListener;复制代码

订阅者经过addEventListener方法来订阅一个事件:wordpress

public bool addEventListener(string eventType, SFListenerSelector sel) {
    if (eventType != "" && sel != null) // 判断有效性
    {
        if (hasEventListener(eventType, sel))
        {
            // SFUtils这个类是我本身弄的,下一篇文章再讲
            SFUtils.log(string.Format("重复监听!type={0}", eventType));
        }
        if (!m_dictListeners.ContainsKey(eventType))
        {
            // 不存在的话就新建一个
            List<SFListenerSelector> newSelectors = new List<SFListenerSelector>();
            m_dictListeners[eventType] = newSelectors;
        }
        var selectors = m_dictListeners[eventType];
        selectors.Add(sel);
        return true;
    }
    return false;
}复制代码

任何人均可以经过发布者(一般来讲是发布者本身)来发布事件:函数

public int dispatchEvent(SFEvent e) {
    int count = 0;
    if (m_dictListeners.ContainsKey(e.eventType))
    {
        var selectors = m_dictListeners[e.eventType];
        foreach (var item in selectors)
        {
            item(e);
            count += 1;
        }
    }
    return count;
}复制代码

用途相关

其实更常见的使用场景是在UI,我此次用的是Unity5自带的UGUI,写了一个控件来结合Unity的事件系统和我这个事件系统,实际开发的时候使用UI事件的方式和使用普通事件的方式是彻底一致的,这个咱们后面再详细介绍学习

完整代码

上面贴出的代码片断因为篇幅限制只保留了关键部分,完整的代码可在个人github上找到

相关文章
相关标签/搜索