还记得我们的简易消息机制是为了解决什么问题诞生的嘛? 是为了解决脚本间访问的问题。 我们回过头再看下 A 脚本如果想访问 B 脚本,使用消息机制,如何实现。 代码如下: 用法还是很简单的。 不过假如我们的 B 脚本注册了非常多的消息,代码会变成如下: 每次注册一个消息,对应地,在 OnDestroy 操作的时候就要注销一个事件。这个非常像我们写 C++ 的时候遵循的一个内存管理法则,每次申请内存就要在析构方法里进行释放。 而这样使用消息机制,初学者非常容易忘记消息的注销,从而导致引用异常等等。 那么如何解决呢? 用一个 Dictionary 记录这个脚本中已经注册过的消息,以及消息名对应的回调。 代码如下: 这样,不管注册了多少个消息,只要在 OnDestroy 的时候, 进行一个遍历,这样消息就全部注销掉了。 但是这样写的话注册,就变得麻烦了,每次注册要先两行代码。 把两行提取成一个方法就好了。 而注册消息的代码就会变成如下: 是不是精简了很多,而且也可以注册 Lambda 表达式了。 不过我们看下现在的 B 脚本全部代码: 目前,每个要使用相同消息策略的脚本,都实现如上的代码,会产生很多的重复代码。所以这里我们要开始考虑如何让这个消息注册/注销的策略进行复用。首先用静态方法是不可能了,因为这个策略是有状态的(成员变量)。所以以我们目前掌握的知识来看,只能用继承的方式了。 继承也有两种,一种是继承一个新类,另一种是继承到 MonoBehaviourSimplify 里。 笔者选择后者,这样我们的脚本只要继承 MonoBehaviourSimplify 就会获得 API 简化和消息功能了,一举多得,而且很方便。 集成后的代码,也就是第十三个示例的代码如下: 在以上代码里,笔者把 MonoBehaviourSimplify 添加了 abstract 关键字,这样用户在使用 MonoBehaviourSimplify 的时候就不能自己创建出来实例了。 而又添加了如下抽象方法: 做这步的目的呢,是为了提醒子类不要覆写了 OnDestroy。提醒是怎么做到的呢。 我们通过分析可以得出,使用 MonoBehaviourSimplify 的情况有两种。 第二种呢,脚本本来就有了,但是在中途想要换成继承 MonoBehaviourSimplify,继承了之后,同样报错了,报错了之后发现 MonoBehaviourSimplify 推荐用 OnBeforeDestroy 来做卸载逻辑,这时候如果以前的脚本已经有了 OnDestroy 逻辑,用户就会把 OnDestroy 的逻辑迁移到 OnBeforeDestroy 里。这样也算达到了一个提醒的作用。 这就是 OnBeforeDestroy 的设计初衷,而 abstract 关键字,就应该这样用。 但是到这里呢,这套策略还是有一点小问题的。这个小问题就留在下一篇讲了。 今天的内容就这些,我们下一篇再见。 转载请注明地址:凉鞋的笔记:liangxiegame.com QFramework 地址:https://github.com/liangxiegame/QFramework QQ 交流群:623597263 Unity 进阶小班: 关注公众号:liangxiegame 获取第一时间更新通知及更多的免费内容。public class A : MonoBehaviour { void Update() { if(Input.GetMouseButtonDown(0)) { MsgDispatcher.Send("DO","ok"); } } } public class B : MonoBehaviour { void Awake() { MsgDispatcher.Register("DO",DoSomething); } void DoSomething(object data) { // do something } void OnDestroy() { MsgDispatcher.UnRegiter("DO",DoSomething); } }
public class B : MonoBehaviour { void Awake() { MsgDispatcher.Register("DO",DoSomething); MsgDispatcher.Register("DO1",MsgReceiver); MsgDispatcher.Register("DO2",MsgReceiver1); MsgDispatcher.Register("DO3",MsgReceiver2); } void DoSomething(object data) { // do something } ... void OnDestroy() { MsgDispatcher.UnRegiter("DO",DoSomething); MsgDispatcher.UnRegiter("DO1",MsgReceiver); MsgDispatcher.UnRegiter("DO2",MsgReceiver1); MsgDispatcher.UnRegiter("DO3",MsgReceiver2); } }
public class B : MonoBehaviour { Dictionary<string,Action<object>> mMsgRegisterRecorder = new Dictionary<string,Action<object>>(); void Awake() { MsgDispatcher.Register("DO",DoSomething); mMsgRegisterRecorder.Add("DO",DoSomething); MsgDispatcher.Register("DO1",MsgReceiver); mMsgRegisterRecorder.Add("DO1",MsgReceiver); MsgDispatcher.Register("DO2",MsgReceiver1); mMsgRegisterRecorder.Add("DO2",MsgReceiver1); MsgDispatcher.Register("DO3",MsgReceiver2); mMsgRegisterRecorder.Add("DO3",MsgReceiver2); } void DoSomething(object data) { // do something } ... void OnDestroy() { foreach (var keyValuePair in mMsgRegisterRecorder) { MsgDispatcher.UnRegister(keyValuePair.Key,keyValuePair.Value); } mMsgRegisterRecorder.Clear(); } }
MsgDispatcher.Register("DO3",MsgReceiver2); mMsgRegisterRecorder.Add("DO3",MsgReceiver2);
提取的方法,代码如下:private void RegisterMsg(string msgName, Action<object> onMsgReceived) { MsgDispatcher.Register(msgName, onMsgReceived); mMsgRegisterRecorder.Add(msgName, onMsgReceived); }
private void Awake() { RegisterMsg("Do",DoSomething); RegisterMsg("DO1",MsgReceiver); RegisterMsg("DO2", _=>{ }); RegisterMsg("DO3", _=>{ }); }
public class B : MonoBehaviour { Dictionary<string, Action<object>> mMsgRegisterRecorder = new Dictionary<string, Action<object>>(); private void Awake() { RegisterMsg("Do",DoSomething); RegisterMsg("DO1",_=>{ }); RegisterMsg("DO2", _=>{ }); RegisterMsg("DO3", _=>{ }); } private void RegisterMsg(string msgName, Action<object> onMsgReceived) { MsgDispatcher.Register(msgName, onMsgReceived); mMsgRegisterRecorder.Add(msgName, onMsgReceived); } void DoSomething(object data) { // do something } private void OnDestroy() { foreach (var keyValuePair in mMsgRegisterRecorder) { MsgDispatcher.UnRegister(keyValuePair.Key,keyValuePair.Value); } mMsgRegisterRecorder.Clear(); } }
using System; using System.Collections.Generic; namespace QFramework { public abstract partial class MonoBehaviourSimplify { Dictionary<string, Action<object>> mMsgRegisterRecorder = new Dictionary<string, Action<object>>(); protected void RegisterMsg(string msgName, Action<object> onMsgReceived) { MsgDispatcher.Register(msgName, onMsgReceived); mMsgRegisterRecorder.Add(msgName, onMsgReceived); } private void OnDestroy() { OnBeforeDestroy(); foreach (var keyValuePair in mMsgRegisterRecorder) { MsgDispatcher.UnRegister(keyValuePair.Key,keyValuePair.Value); } mMsgRegisterRecorder.Clear(); } protected abstract void OnBeforeDestroy(); } public class B : MonoBehaviourSimplify { private void Awake() { RegisterMsg("Do", DoSomething); RegisterMsg("DO1", _ => { }); RegisterMsg("DO2", _ => { }); RegisterMsg("DO3", _ => { }); } void DoSomething(object data) { // do something } protected override void OnBeforeDestroy() { } } }
protected abstract void OnBeforeDestroy();
一种是,在写脚本之前就想好了这个脚本要继承 MonoBehaviourSimplify,但是继承之后,编译会报错,因为有一个抽象方法,必须实现,也就是 OnBeforeDestroy。那么实现了这个,用户就会知道设计 MonoBehaviourSimplify 的人,是推荐用 OnBeforeDestroy 来做卸载逻辑的,并不推荐用 OnDestroy。这是第一种。更多内容
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算