Unity 事件中心

Unity 事件中心

为了降低模块与模块之间的耦合,举个例子如下图
关系图1

有 boss、player、winpanle(游戏胜利界面) ,当boss死亡时,玩家得到一定金币,游戏胜利面板弹出。通常的做法是在Boss脚本里 得到player 和 winpanle 的实例对象,然后再调用其对应函数

此做法简单,对于不复杂的业务逻辑比较友好也方便,但是对于稍微复杂点的业务逻辑就显得很混乱,模块间的耦合性也非常高 如图
关系图2

这还只是4个模块间相互引用,更复杂的可能有几十个或上百,解决这问题就需要用到设计模式中的 发布订阅模式 (Publish–subscribe pattern)
关系图3
boss把死亡消息发给中心(中间人Broker),此后就不用管了,谁需要这个事件 谁就订阅即可,中心会通知这些订阅者。玩家和胜利面板需要知道boss什么时候死亡,于是就订阅boss的死亡事件,boss死后就会收到通知。

UML关系图

关系图4

脚本实现

创建IEventInfo接口EventInfo类,类继承接口

using UnityEngine.Events;

interface IEventInfo { }

public class EventInfo<T> : IEventInfo {
    public UnityAction<T> m_action;
    public EventInfo (UnityAction<T> _action) {
        m_action += _action;
    }
}

事件中心实现 因为是唯一的 所以是单例 需继承单例基类

/// <summary>
/// 事件中心
/// </summary>
public class Evencenter : SingletonBase<Evencenter> {

    private Dictionary<string, IEventInfo> m_eventDic;

    protected override void Init () {
        m_eventDic = new Dictionary<string, IEventInfo> ();
    }

    /// <summary>
    /// 注册监听函数
    /// </summary>
    /// <param name="_eventName">事件名</param>
    /// <param name="_action">回调函数</param>
    /// <typeparam name="T">参数类型</typeparam>
    public void AddEventListener<T> (string _eventName, UnityAction<T> _action) {
        if (!m_eventDic.ContainsKey (_eventName)) {
            m_eventDic.Add (_eventName, new EventInfo<T> (_action));
            return;
        }
        (m_eventDic[_eventName] as EventInfo<T>).m_action += _action;

    }

    /// <summary>
    /// 事件的发布
    /// </summary>
    /// <param name="_eventName">事件名</param>
    /// <param name="_info">事件触发时需要传出去的参数</param>
    /// <typeparam name="T">参数类型</typeparam>
    public void EventTrigger<T> (string _eventName, T _info) {
        if (m_eventDic.ContainsKey (_eventName) && (m_eventDic[_eventName] as EventInfo<T>).m_action != null)
            (m_eventDic[_eventName] as EventInfo<T>).m_action (_info);//里氏转换 把父类转为子类
    }

    /// <summary>
    /// 取消函数监听 一般用于对象销毁
    /// </summary>
    /// <param name="_eventName">事件名</param>
    /// <param name="_action">注册的回调函数</param>
    /// <typeparam name="T">参数类型</typeparam>
    public void RemoveEventListener<T> (string _eventName, UnityAction<T> _action) {
        (m_eventDic[_eventName] as EventInfo<T>).m_action -= _action;
    }

    public void Clear () {
        m_eventDic.Clear ();
    }
}

使用

分别创建boss、player、winpanle的GameObject和对应脚本

public class Boss : MonoBehaviour {
    void Start () {
        Invoke ("Die", 3);//延迟三秒Boss死亡
    }
    //死亡后发布死亡事件
    void Die () {
    	//							回调函数的参数类型  事件名     回调函数参数 这里是boss名字
    	Evencenter.Instance.EventTrigger<string> ("BossDead", "加里奥");
    }
}
public class Player : MonoBehaviour {
    void Start () {
    	//对boss死亡这个事件进行监听 
        Evencenter.Instance.AddEventListener<string> ("BossDead", Fun);
    }
    void Fun (string _bossName) {
        Debug.Log (_bossName + " 死亡 玩家加金币");
    }
	void OnDestroy () {
        Evencenter.Instance.RemoveEventListener<string> ("BossDead", Fun);
    }
}
public class WinPanle : MonoBehaviour {
    void Start () {
        Evencenter.Instance.AddEventListener<string> ("BossDead", (_bossName)=>{
			Debug.Log (_bossName + " 死亡 胜利面板弹出");
		});
    }
}

点击运行按钮不出意外 3秒后 控制台会打印如下信息

在这里插入图片描述

最后

学习笔记,仅供参考,如有不正,欢迎指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值