事件中心模块

假设怪物死亡后,需要做三件事:player得到奖励,更新任务记录,其他包括成就系统、刷新怪物等待,有前后联系,最简单的方法就是找到脚本挂在的对象,然后得到脚本,最后调用脚本中的函数,但这样会让程序的耦合性太强,因此换一个做法,当怪物死亡的时候不和其他方法直接进行关联,而是通知事件中心派发一个事件,将该事件关联的行为(即监听 )进行调用。

public class EventMgr : BaseManager<EventMgr > {
    // key —— 事件的名字
    // value —— 监听的事件对应的委托函数们
    // 通过UnityAction<object>可以用一个类型传任何参数(数组也可以用object表示)
    private Dictionary<string, UnityAction<object>> eventDic = new Dictionary<string, UnityAction<object>>();
    
    // <param name="name"> 事件的名字</param>
    // <param name="action"> 处理事件的委托函数</param>
    public void AddEventListener(string name, UnityAction<object> action) {
        if (eventDic.ContainsKey(name)) {
            eventDic[name] += action;
        } else {
            eventDic.Add(name, action);
        }
    }

    // <param name="name"> 触发的事件</param>
    public void EventTrigger(string name, object params) {
        if (eventDic.ContainsKey(name)) {
            eventDic[name].Invoke(params);
        }
    }

    // 移除委托函数
    public void RemoveEventListener(string name, UnityAction<object> action) {
        if (eventDic.ContansKey(name)) {
            eventDic[name] -= action;
        }
    }

    public void ClearAllListener() {
        // eventDic[name] = null;
        eventDic.Clear();
    }
}
public class Monster : MonoBehaviour {
    public string name = "monster";

    void Start() {
        Dead();
    }

    void Dead() {
        Debug.Log("怪物死亡");

        // 其他对象想在怪物死亡后的行为,比如
        // 1、玩家得到奖励
        // 2、更新任务记录
        // 3、其他(比如成就系统,副本继续刷怪等)
        // TODO.....

        // 分发事件
        EventMgr .GetInstance().EventTrigger("MonsterDead", this);  
    }
}
// -----------------------------------------------
public class Player : MonoBehaviour {
    void Start() {
        EventMgr .GetInstance().AddEventListerner("MonsterDead", MonsterDeadDo);
    }

    public void MonsterDeadDo(object info) {
        Debug.Log("玩家得到奖励");
    }

    void OnDestroy() {
        EventMgr .GetInstance().RemoveEventListener("MonsterDead", MonsterDeadDo);
    }
}
// -----------------------------------------------
public class Task : MonoBehaviour {
    void Start() {
        EventMgr .GetInstance().AddEventListerner("MonsterDead", TaskWaitMonsterDeadDo);
    }

    public void TaskWaitMonsterDeadDo(object info) {
        Debug.Log("任务记录");
    }

    void OnDestroy() {
        EventMgr .GetInstance().RemoveEventListener("MonsterDead", TaskWaitMonsterDeadDo);
    }
}
// -----------------------------------------------
public class Other : MonoBehaviour {
    void Start() {
        EventMgr .GetInstance().AddEventListerner("MonsterDead", OtherWaitMonsterDeadDo);
    }

    public void OtherWaitMonsterDeadDo(object info) {
        Debug.Log("其他要做的事");
    }

    void OnDestroy() {
        EventMgr .GetInstance().RemoveEventListener("MonsterDead", OtherWaitMonsterDeadDo);
    }
}

如果要优化一下装箱拆箱的问题,可以通过里氏替换以及泛型原则进行一个骚操作,如果不需要参数,通过重载

public interface IEventInfo {

}

public class EventInfo<T> : IEventInfo {
    public UnityAction<T> actions;

    public EventInfo( UnityAction<T> action) {
        actions += action;
    }
}

public class EventInfo : IEventInfo {
    public UnityAction actions;

    public EventInfo( UnityAction action) {
        actions += action;
    }
}


public class EventMgr : BaseManager<EventMgr > {
    // key —— 事件的名字
    // value —— 监听的事件对应的委托函数们
    // 通过UnityAction<object>可以用一个类型传任何参数(数组也可以用object表示)
    private Dictionary<string, IEventInfo > eventDic = new Dictionary<string, IEventInfo >();
    
    // <param name="name"> 事件的名字</param>
    // <param name="action"> 处理事件的委托函数</param>
    public void AddEventListener<T>(string name, UnityAction<T> action) {
        if (eventDic.ContainsKey(name)) {
            (eventDic[name] as EventInfo<T>).actions += action;
        } else {
            eventDic.Add(name, new EventInfo<T>(action));
        }
    }



    public void AddEventListener(string name, UnityAction action) {
        if (eventDic.ContainsKey(name)) {
            (eventDic[name] as EventInfo).actions += action;
        } else {
            eventDic.Add(name, new EventInfo(action));
        }
    }

    // <param name="name"> 触发的事件</param>
    public void EventTrigger<T>(string name, T params) {
        if (eventDic.ContainsKey(name)) {
            if ((eventDic[name] as EventInfo<T>).actions != null) 
                (eventDic[name] as EventInfo<T>).actions.Invoke(params);
        }
    }

    public void EventTrigger(string name) {
        if (eventDic.ContainsKey(name)) {
            if ((eventDic[name] as EventInfo).actions != null) 
                (eventDic[name] as EventInfo).actions.Invoke();
        }
    }

    // 移除委托函数
    public void RemoveEventListener<T>(string name, UnityAction<T> action) {
        if (eventDic.ContansKey(name)) {
            (eventDic[name] as EventInfo<T>).actions -= action;
        }
    }

    public void RemoveEventListener(string name, UnityAction action) {
        if (eventDic.ContansKey(name)) {
            (eventDic[name] as EventInfo).actions -= action;
        }
    }

    public void ClearAllListener() {
        // eventDic[name] = null;
        eventDic.Clear();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值