Unity设计模式03_事件中心

整理自:Bilibili-唐老湿的Unity程序基础框架

1.问题的引入
假设场景中有这样几个GameObject:
在这里插入图片描述
我们需要实现的是在Monster死亡时,让Player经验值增加,Task处理任务进度,Other处理其他怪物死后该做的事情
那么这个代码大概是:

	 public void MonsterDead()
	{
		GameObject.Find("Task").GetComponent<Task>().TaskDoWhenMonsterDead();
		GameObject.Find("Other").GetComponent<Other>().OtherDoWhenMonsterDead();
		GameObject.Find("Player").GetComponent<Player>().PlayDoWhenMonsterDead();
	}

需要找到其他的各个GameObject,获取脚本,然后再调用函数,如果还有其他的一大堆GameObject要响应这个事件(耦合度高),或者是其他GameObject也需要这样调用另外的GameObject的脚本函数,可以说很麻烦了。
这个时候就需要引入事件中心。

2.事件中心:
大致思路:当怪物死后,向事件中心发出一个消息(怪物挂了),这些需要响应的GameObject中的函数做成一个多播委托事件中心调用来响应这个消息。

3.编码:
数据结构:这个发出的消息可以用String来存放,而委托则用unity自带的UnityAction即可,在调用时可能需要传参,参数类型可设置为万能的Object,由于这些消息和委托一一对应,即可用键值对的方式(Dictionary)表示,则可以表示为:

    Dictionary<string,UnityAction<Object>> dic = new Dictionary<string, UnityAction<Object>>();

整个事件中心代码:

public class EventCenter : SingeCaseBase<EventCenter>
{
    Dictionary<string,UnityAction<Object>> dic = new Dictionary<string, UnityAction<Object>>();
    /// <summary>
    /// 添加监听事件
    /// </summary>
    /// <param name="eventName"></param>
    /// <param name="action"></param>
    public void AddEventListener(string eventName,UnityAction<Object> action)
    {
        if(dic.ContainsKey(eventName))
        {
            dic[eventName] += action;
        }
        else
        {
            dic.Add(eventName, action);
        }
    }
    /// <summary>
    /// 当事件触发
    /// </summary>
    /// <param name="evenName"></param>
    public void EventTrigger(string eventName,Object info)
    {
        if(dic.ContainsKey(eventName))
        {
            dic[eventName](info);
        }
    }
    /// <summary>
    /// 移除委托
    /// </summary>
    /// <param name="eventName"></param>
    /// <param name="action"></param>
    public void RemoveAction(string eventName,UnityAction<Object> action)
    {
        if(dic.ContainsKey(eventName))
        {
            dic[eventName] -= action;
        }
    }
    /// <summary>
    /// 清空所有事件
    /// </summary>
    public void Clear()
    {
        dic.Clear();
    }

}
}

以Player的响应为例:

public class Player : MonoBehaviour
{
    private void Start()
    {
        EventCenter.GetInstance().AddEventListener("MonsterDead", PlayDoWhenMonsterDead);
    }
    public void PlayDoWhenMonsterDead(Object info)
    {
        Debug.Log("The Player Adds Exp"+ (info as Monster).addExp);
    }
    /// <summary>
    /// 死亡时移除对应委托【特别注意】
    /// </summary>
    private void OnDestroy()
    {
        EventCenter.GetInstance().RemoveAction("MonsterDead", PlayDoWhenMonsterDead);
    }
}

注意:一定要注意在物体Destroy时移除委托,在场景切换时清空所有事件

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值