Unity游戏框架学习笔记——03基于观察者模式的事件中心

基于观察者模式的事件中心

一如既往指路牌:https://www.bilibili.com/video/BV1C441117wU?p=5.
视频原本是免费的,完整视频移步泰课吧/(ㄒoㄒ)/~~…
泰课指路牌:https://www.taikr.com/course/1062/task/31006/show.

引入

对于一般写脚本的话,如果要实现监听某个状态,让脚本在该状态下实现相应动作的执行,都是在更新这个状态对应的脚本里,判断该状态为真后,获取其余对象中关心该状态的脚本里方法来执行。

举个栗子:

怪物的身上挂着一个Monster脚本,其中有一个方法MonsterDead();
然后
玩家关心奖励,玩家身上有一个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();
}

可以看出,在Monster脚本里,不可避免地出现了很多其他脚本的方法
那么我们不妨夸张的想一想,当一个游戏很大,里面的功能也更加多的时候,上述这样的情况是不是就会出现得更加频繁,脚本和脚本之间联系也会乱七八糟,这个时候脚本之间就出现所说的耦合性较大的情况,而且脚本之间也会很复杂
如果在这个时候,要额外增加一些功能的话,就会牵一发而动全身了,大改自然是必须的了。
于是为了降低程序之间的耦合性,较小复杂性,提高开发效率,基于观察者模式的事件中心,也就应运而生了。

事件中心

事件中心就是字面上的意思,具体实现的功能就是负责事件的记录和分发。
比如说当怪物死亡,那么怪物就向事件中心公布派发出“怪物死亡了”这个事件,事件中心接收到之后,就会提醒订阅了该事件的方法,让关心这个事件的方法执行。

代码

/// <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;}

那么就需要在对象销毁时,在OnDestory()中调用该方法,将订阅的事件移除。

功能完善


由于事件中心类的单例特性,在内存中是静态区域的,即在程序一开始的时候分配内存空间,直至程序结束时才会释放,那么在场景切换时,下一个场景的内存中还会保留着上一个场景的事件订阅,虽然有对象销毁时的事件监听移除,但为以防万一,还是把事件中心里面的事件监听给移除要好一点。

    /// <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

object 是泛类, 引用的是System.Object.

Object 引用的是UnityEngine.Object,是Unity所有组件Component和GameObject的父类;

UnityEngine.Object继承System.Object.

Unity游戏框架学习笔记——03基于观察者模式的事件中心相关推荐

  1. unity游戏框架学习-框架结构

    转眼毕业三年了,算上实习差不多四年的游戏开发了,一直想自己鼓捣套框架,奈何能力太次,不知道从哪开始.但是万事开头难,总要踏出第一步,才会有后面的两步,三步- 我认为的unity游戏框架就是一整套的工具 ...

  2. [Unity] ACT 战斗系统学习 1:基于委托的事件管理器

    我觉得看视频太慢了,还是看别人源码更快-- 1.664235822/DarkSouls-Demo Github 源码: https://github.com/664235822/DarkSouls-D ...

  3. Unity程序框架总结归置系列(3)——事件中心

    上一篇--Unity程序框架总结归置系列(2)--对象池 依然是话不多说,直接肝. /// <summary> /// 事件中心 /// </summary> public c ...

  4. MyBatis框架学习笔记03:利用MyBatis实现关联查询

    文章目录 一.查询需求 (一)针对三张表关联查询 (二)按班级编号查询班级信息 (三)查询全部班级信息 二.创建数据库表 (一)创建教师表 (二)创建班级表 (三)创建学生表 三.创建与数据库表对应的 ...

  5. Spring框架学习笔记03:初探Spring——利用注解配置类取代Spring配置文件

    文章目录 一.课程引入 二.利用注解配置类取代Spring配置文件 (一)打开项目[SpringDemo2021] (二)创建net.hw.spring.lesson03包 (三)移植上一讲的接口和类 ...

  6. 从零写一个具有IOC-AOP-MVC功能的框架---学习笔记---11. MVC功能之http请求处理器的编写---简易框架最后一公里!

    从零写一个具有IOC-AOP-MVC功能的框架-学习笔记 专栏往期文章链接: IOC功能相关章节: 从零写一个具有IOC-AOP-MVC功能的框架-学习笔记-01.项目初始化 从零写一个具有IOC-A ...

  7. 《Unity API常用方法和类详细讲解—Siki学院》课程学习笔记03

    <Unity API常用方法和类详细讲解-Siki学院>课程学习笔记03 课时18-20协程及其执行 1.使用Coroutine实现颜色动画渐变 void Update(){if (Inp ...

  8. C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)【1】

    C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)[1] 前言: 本笔记作为记录我从零开始学习C#的记录,为了unity的兴趣爱好自学一门C#,也算是寒假为自己充个电,希望这个寒假可以坚持下去 ...

  9. 天池龙珠训练营-机器学习学习笔记-03 LightGBM 分类

    天池龙珠训练营-机器学习学习笔记-03 LightGBM 分类 本学习笔记为阿里云天池龙珠计划机器学习训练营的学习内容,学习链接为:训练营 一 原理简介: 它是一款基于GBDT(梯度提升决策树)算法的 ...

最新文章

  1. 【Linux 操作系统】阿里云服务器 操作实战 部署C语言开发环境(vim配置,gcc) 部署J2EE网站(jdk,tomcat)
  2. Activiti之 Exclusive Gateway
  3. 21-5-22校赛J 下围棋
  4. VS2008和.NET3.5的学习资源
  5. AWS elastic load balancer里的监听器certificate设置
  6. 学习vim 从常用按键开始
  7. nvidia cuda工具包更新9.0版本记录
  8. 从卓越工程的角度看微软中国开发团队的成长 (一)
  9. 2021年奎屯七中高考成绩查询,奎屯高考成绩查询
  10. const限定符用法汇总
  11. pip安装python依赖成功,pycharm中import出错
  12. Linux_access the file or directory which start with -
  13. (自用)Linux系统彻底卸载MySQL数据库
  14. U8恢复记账操作步骤
  15. 成手指状态html,css手势状态定义属性cursor和自定义鼠标手势详解
  16. 2017.11.06 ~ 11.10 NOIP八连测滚粗记
  17. 直播预告| ICML专场四~
  18. php的left join,Left Join
  19. 安装 Dashboard
  20. 初探Java设计模式5:一文了解Spring涉及到的9种设计模式

热门文章

  1. html实现网页夜间模式,通过JS和PHP实现网站夜间模式的自动切换
  2. Surging -Demo部署
  3. 3.开发java的三个步骤
  4. Rego不好用?用Pipy实现OPA
  5. 卡西欧计算机储存公式,注意!CPA考试时计算器你带对了吗!
  6. VS2015主题设置
  7. 9.1.3 定点数类型
  8. win10家庭版转专业版后,专业版功能仍然不能用怎么办
  9. 【Java】剑指Offer_编程题_机器人的运动范围
  10. 华一汽车科技中控大屏的发展