Unity游戏框架学习笔记——03基于观察者模式的事件中心 一如既往指路牌:https://www.bilibili.com/video/BV1C441117wU?p=5. 对于一般写脚本的话,如果要实现监听某个状态,让脚本在该状态下实现相应动作的执行,都是在更新这个状态对应的脚本里,判断该状态为真后,获取其余对象中关心该状态的脚本里方法来执行。 怪物的身上挂着一个Monster脚本,其中有一个方法MonsterDead(); 那么 可以看出,在Monster脚本里,不可避免地出现了很多其他脚本的方法。 事件中心就是字面上的意思,具体实现的功能就是负责事件的记录和分发。 在关心这个事件的对象的脚本中, 那么这个时候就会存在一个问题: 那么就需要在对象销毁时,在OnDestory()中调用该方法,将订阅的事件移除。 ① ② object 是泛类, 引用的是System.Object. Object 引用的是UnityEngine.Object,是Unity所有组件Component和GameObject的父类; UnityEngine.Object继承System.Object.基于观察者模式的事件中心
引入
举个栗子:
然后
玩家关心奖励,玩家身上有一个Player脚本,里面有一个PlayerWaitMonsterDead()方法会在怪物死亡执行一些操作;
任务系统会更新,任务系统身上也有一个Task脚本,里面有TaskWaitMonsterDead()方法是关心怪物死亡的;
其他的一些同样关心怪物死亡的脚本也是一样有相关方法;
当怪物死亡时,如果要通知这些脚本执行关心怪物死亡的方法的话,我们一般也是在怪物脚本的MonsterDead()方法里面,获取相关的脚本,执行相应方法:
MonsterDead()
{
// Monster Dead //
GameObject.Find(“Player”).GetComponent< Player >().PlayerWaitMonsterDead();
GameObject.Find(“Task”).GetComponent< Task >().TaskWaitMonsterDead();
GameObject.Find(“Other”).GetComponent< Other >().OtherWaitMonsterDead();
}
那么我们不妨夸张的想一想,当一个游戏很大,里面的功能也更加多的时候,上述这样的情况是不是就会出现得更加频繁,脚本和脚本之间联系也会乱七八糟,这个时候脚本之间就出现所说的耦合性较大的情况,而且脚本之间也会很复杂。
如果在这个时候,要额外增加一些功能的话,就会牵一发而动全身了,大改自然是必须的了。
于是为了降低程序之间的耦合性,较小复杂性,提高开发效率,基于观察者模式的事件中心,也就应运而生了。事件中心
比如说当怪物死亡,那么怪物就向事件中心公布派发出“怪物死亡了”这个事件,事件中心接收到之后,就会提醒订阅了该事件的方法,让关心这个事件的方法执行。代码
/// <summary> /// 事件中心类 /// </summary> public class EventCenter : Singleton<EventCenter> { // key —— 时间名字 // value —— 关心这个事件的委托方法们 public Dictionary<string, UnityAction> eventsDictonary = new Dictionary<string, UnityAction>(); /// <summary> /// 给关心这个事件的方法提供监听(订阅) /// </summary> /// <param name="eventName"></param> /// <param name="action"></param> public void EventAddListener(string eventName, UnityAction action) { // 存在存在要监听的事件 if (eventsDictonary.ContainsKey(eventName)) { eventsDictonary[eventName]+= action; } // 要监听的事件不存在,添加对应事件和订阅后执行的方法 else { eventsDictonary.Add(eventName,action); } } /// <summary> /// 事件触发 /// </summary> /// <param name="EventName">触发的事件名字</param> public void EventTrigger(string eventName) { // 存在存在要监听的事件,依次执行订阅了的委托方法 if (eventsDictonary.ContainsKey(eventName)) { // eventsDictonary[eventName](); eventsDictonary[eventName].Invoke(); } } }
使用
在对象生成时,即在Start()函数体中,添加订阅即可。
挂载该脚本的对象一旦被销毁,但事件中心中仍然保持着这个对象的方法对事件的监听,会导致内存泄露,因为对于这个事件监听的引用依然存在,所以,在添加了监听之后,在对象的销毁时,要对监听事件经行移除。 /// <summary> /// 移除事件监听 /// </summary> /// <param name="eventName">监听的事件名称</param> /// <param name="action">监听事件的委托方法</param> public void RemoveListener(string eventName, UnityAction action) { if (eventsDictonary.ContainsKey(eventName)) eventsDictonary[eventName] -= action; }
功能完善
由于事件中心类的单例特性,在内存中是静态区域的,即在程序一开始的时候分配内存空间,直至程序结束时才会释放,那么在场景切换时,下一个场景的内存中还会保留着上一个场景的事件订阅,虽然有对象销毁时的事件监听移除,但为以防万一,还是把事件中心里面的事件监听给移除要好一点。 /// <summary> /// 清楚所有事件以及监听关系 /// 主要用在场景切换时 /// </summary> public void ClearEvent() { eventsDictonary.Clear(); }
解决监听方法执行的信息传递,将委托方法改为Object类型的参数/// <summary> /// 事件中心类 /// </summary> public class EventCenter : Singleton<EventCenter> { // key —— 时间名字 // value —— 关心这个事件的委托方法们 public Dictionary<string, UnityAction<object>> eventsDictonary = new Dictionary<string, UnityAction<object>>(); /// <summary> /// 给关心这个事件的方法提供监听(订阅) /// </summary> /// <param name="eventName"></param> /// <param name="action"></param> public void EventAddListener(string eventName, UnityAction<object> action) { // 存在存在要监听的事件 if (eventsDictonary.ContainsKey(eventName)) { eventsDictonary[eventName]+= action; } // 要监听的事件不存在,添加对应事件和订阅后执行的方法 else { eventsDictonary.Add(eventName,action); } } /// <summary> /// 事件触发 /// </summary> /// <param name="eventName">触发事件的名字</param> /// <param name="info">传递的参数消息</param> public void EventTrigger(string eventName, object info) { // 存在存在要监听的事件,依次执行订阅了的委托方法 if (eventsDictonary.ContainsKey(eventName)) { // eventsDictonary[eventName](info); eventsDictonary[eventName].Invoke(info); } } /// <summary> /// 移除事件监听 /// </summary> /// <param name="eventName">监听的事件名称</param> /// <param name="action">监听事件的委托方法</param> public void RemoveListener(string eventName, UnityAction<object> action) { if (eventsDictonary.ContainsKey(eventName)) eventsDictonary[eventName] -= action; } /// <summary> /// 清楚所有事件以及监听关系 /// 主要用在场景切换时 /// </summary> public void ClearEvent() { eventsDictonary.Clear(); } }
关于 Object 和 object
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算