Event Center Model In Unity
这篇文章将在Unity中实现事件中心模块,在此之前我先引入一个情境:
当玩家打败Boss时,Boss会掉落物品、同时会播放玩家胜利动画、如果是第一次击败Boss还会进行成就播报、NPC会为你庆祝(甚至开一场party)……
Q1:天啊!这么多的事情!??!弓虽!是我的话要在好多个脚本中写上好多好多逻辑,我还会为怪物、玩家、成就、NPC添加一堆状态,这样让除自己之外的脚本也知道自己发生了什么改变,想想就头疼……
A:无需担心!读者,或许我该称呼你为元读者?本文就是告诉你解耦的方式的。:)
Q2:作者,哦不,元作者,解耦是啥?
A:解耦,用我的话说,就是把莲藕的丝切断,如果能弄干净就好了,不然吃莲藕的时候还得吃一脸丝。在程序里,就是各个脚本负责某个特定功能,不要插足别的事情,到时候在脚本间的决策阶段会很麻烦,脚本和脚本打架,就像《千与千寻》中锅炉爷爷说的”不要抢走别人的工作“,哈哈哈,跑题了。
A:在此之前,我将介绍一下观察者模式,在我上面举的例子当中,有怪物、成就、玩家和NPC,其中一个部分发生变化,其他的部分也要发生改变。这时,我就会建一个中转站,怪物死了,叫个信使告诉我”怪物死了“,然后这个中转站再告诉其他地方”怪物死了“这个消息,然后各处都要求我做一些事情——各个地方告诉我的事情,我会在收到要执行这件事的消息后才去执行。这个中转站就是今天要介绍的事件中心。
事件中心需要具备:
- 添加各个地方要求的事件
- 移除某个地方要求的事件
- 条件满足时执行事件
- 事件中心用于存储事件容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class EventCenter : SingletonMonoBase<EventCenter> { private Dictionary<string, UnityAction<object>> eventDic = new Dictionary<string, UnityAction<object>>(); public void AddListener(string name,UnityAction<object> func) { if (eventDic.ContainsKey(name)) { eventDic[name] += func; } else { eventDic.Add(name, func); } } public void RemoveListener(string name) { if (eventDic.ContainsKey(name)) eventDic.Remove(name); return; } public void RemoveAllListener() { eventDic = null; } public void EventTrigger(string name,object info) { if (eventDic.ContainsKey(name)) { eventDic[name].Invoke(info); } else { Debug.Log("来自事件中心:EventTrigger()未能找到要触发的事件"); } } }
|
Q1:为什么字典的值为UnityAction<object>?
A:UnityAction是Unity提供的委托类。(1)有参数是因为我们可能希望在分发事件的时候,别的地方要告诉我们一些信息,这样一来我们才能根据它们提供的信息知道要怎么做这些事件。(2)参数类型为object是因为它是万物之父,用它作为参数,什么都可以传进去,无论是自定义类还是数组等数据结构类,都不在话下。
Q2:可以介绍一下如何使用事件中心吗?
A:正合我意:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Player : MonoBehaviour { private void Start() { EventCenter.GetInstance().AddListener("怪物死了",DebugWaitingForMonsterDied); } public void DebugWaitingForMonsterDied(Object info) { Debug.Log($"怪物死了,该播放动画了,这是怪物的遗言{info}"); } }
public class Monster { public void Died() { EventCenter.GetInstance().EventTrigger("怪物死了","我死得不甘心啊"); } }
|
好的,今天到此为止…… :)