首页 >> 大全

Unity3D基于事件机制的消息系统

2023-11-05 大全 35 作者:考证青年

又到了周末时间,今天没有去公司赚加班费,在家里好好休息一下?不存在的,这辈子不写代码是不存在的!

今天我们来讲讲消息系统。

很多刚入行的小白同学在处理类与类之间的关系时,总是比较简单除暴的处理,直接把那个类引用到这个类,把这个类引用到那个类,最后造成很多类相互引用,形成一个复杂的蜘蛛网式的引用关系,这就是代码的耦合。那这个又有什么关系呢?那么我们就通俗的讲一下这个问题。

打个比方,同学们的期末成绩出来了,然后学校派一个人到全校的学生家里一个个通知成绩,第二天这个人辞职了哈哈!那么学校会怎么做呢?在远古时代,学校一般都是会在学校的公示栏上公布所有学生的期末成绩,而在如今的互联网时代,学校一般都是把所有学生的期末成绩发布到自己系统内,想要知道成绩的同学自己去查看,这样就不会有人辞职了哈哈。学校的系统不认识是哪个学生,也不关心哪个学生要不要看自己的成绩,反正我发布出去了,有兴趣要看的同学可以自己去查看,我们之间没有任何的绯闻,你成绩好不好和我没关系。

这个过程就叫解耦,类与类之间不再有耦合关系,没有小三,也没有小四,家和万事兴。

所以我们引入了事件机制,事件机制其实是一种叫做观察者模式的设计模式,事件的本质是一种方法的委托(),把回调方法委托到事件管理器,当条件达到时,通过事件key来告诉事件管理器可以执行那些委托的方法。

好了,接下来XM就为大家讲解一套完整的消息系统。

1.首先我们先来定义一下消息结构的接口

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc: 
// **********************************************************************using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IMessage
{/// /// 事件类型,Key/// int Type { get; set; }/// /// 发送者/// System.Object Sender { get; set; }/// /// 参数/// System.Object[] Params { get; set; }/// /// 转字符串/// /// string ToString();
}

为什么我会用int类型而不是用类型作为消息的key呢?大家可以自己思考一下。

2.接口的实现。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc: 
// **********************************************************************using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Message : IMessage {public int Type { get; set; }public System.Object[] Params { get; set; }public System.Object Sender { get; set; }public override string ToString(){string arg = null;if (Params != null){for (int i = 0; i < Params.Length; i++){if ((Params.Length > 1 && Params.Length - 1 == i) || Params.Length == 1){arg += Params[i];}else{arg += Params[i] + " , ";}}}return Type + " [ " + ((Sender == null) ? "null" : Sender.ToString()) + " ] " + " [ " + ((arg == null) ? "null" : arg.ToString()) + " ] ";}public Message Clone(){return new Message(Type, Params, Sender);}public Message(int type){Type = type;}public Message(int type, params System.Object[] param){Type = type;Params = param;}public Message(int type, System.Object sender, params System.Object[] param){Type = type;Params = param;Sender = sender;}
}

3.接下来我们定义一下消息的类型,这里我把消息类型分成了常用消息,战斗消息,协议消息3大类,而不是都写在一个类型里面,结构清晰明了。

Unity3D基于事件机制的消息系统__Unity3D基于事件机制的消息系统

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc: 消息的类型
// **********************************************************************/// 
/// 消息的类型  
/// 
public enum MessageType
{/// /// 启动/// START_UP = 1000,/// /// 解压/// UNPACK,/// /// 更新/// UPDATE,/// /// 更新完成/// UPDATE_COMPLETE,
}/// 
/// 战斗的类型
/// 
public enum BattleEvent
{/// /// 攻击/// Attack = 10000,
}/// 
/// 协议的类型
/// 
public enum ProtocolEvent
{}

4.然后我们定义一下消息派发者的接口。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc: 
// **********************************************************************using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IDispatcher
{void AddListener(int type, EventListenerDelegate listener);void RemoveListener(int type, EventListenerDelegate listener);void SendMessage(Message evt);void SendMessage(int type, params System.Object[] param);void Clear();
}

5.接口的实现。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc: 
// **********************************************************************using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public delegate void EventListenerDelegate(Message evt);public class Dispatcher : Singleton, IDispatcher
{private Dictionary events = new Dictionary();public void AddListener(int type, EventListenerDelegate listener){if (listener == null){XMDebug.LogError("AddListener: listener不能为空");return;}EventListenerDelegate myListener = null;events.TryGetValue(type, out myListener);events[type] = (EventListenerDelegate)Delegate.Combine(myListener, listener);}public void RemoveListener(int type, EventListenerDelegate listener){if (listener == null){XMDebug.LogError("RemoveListener: listener不能为空");return;}events[type] = (EventListenerDelegate)Delegate.Remove(events[type], listener);}public void Clear(){events.Clear();}public void SendMessage(Message evt){EventListenerDelegate listenerDelegate;if (events.TryGetValue(evt.Type, out listenerDelegate)){try{if (listenerDelegate != null){listenerDelegate(evt);}}catch (System.Exception e){XMDebug.LogError("SendMessage:", evt.Type.ToString(), e.Message, e.StackTrace, e);}}}public void SendMessage(int type, params System.Object[] param){EventListenerDelegate listenerDelegate;if (events.TryGetValue(type, out listenerDelegate)){Message evt = new Message(type, param);try{if (listenerDelegate != null){listenerDelegate(evt);}}catch (System.Exception e){XMDebug.LogError("SendMessage:", evt.Type.ToString(), e.Message, e.StackTrace, e);}}}public void AddListener(MessageType type, EventListenerDelegate listener){AddListener((int)type, listener);}public void AddListener(BattleEvent type, EventListenerDelegate listener){AddListener((int)type, listener);}public void AddListener(ProtocolEvent type, EventListenerDelegate listener){AddListener((int)type, listener);}public void RemoveListener(MessageType type, EventListenerDelegate listener){RemoveListener((int)type, listener);}public void RemoveListener(BattleEvent type, EventListenerDelegate listener){RemoveListener((int)type, listener);}public void RemoveListener(ProtocolEvent type, EventListenerDelegate listener){RemoveListener((int)type, listener);}public void SendMessage(MessageType type, params System.Object[] param){SendMessage((int)type, param);}public void SendMessage(BattleEvent type, params System.Object[] param){SendMessage((int)type, param);}public void SendMessage(ProtocolEvent type, params System.Object[] param){SendMessage((int)type, param);}
}

我为每个实现接口的方法又重新封装了3个重载方法,这里主要是为了区分消息的类型,方便更好的维护我们的框架,希望同学们都能养成这样的编写代码习惯。

最后,为了不要再让有人因为跑腿辞职,我们还是用好消息系统,不然他们就要跑去送外卖了

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了