Unity-基于面向对象多态特征的消息收发机制

在开发中我们避免不了各个模块之间的消息传递,因此总结此消息收发机制。
这里写图片描述

MonoBase类
首先是扩展MonoBehaviour的基类:MonoBase
此类的就是为了让MonoBehaviour的功能更加强大

public class MonoBase : MonoBehaviour 
{
    /// <summary>
    /// 定义一个虚方法
    /// </summary>
    public virtual void Execute(int eventCode, object message)
    {
    }
}

消息处理中心类:MessageCenter
只是负责消息的转发

public class MsgCenter : MonoBase
{
    public static MsgCenter Instance = null;

    void Awake()
    {
        Instance = this;

        gameObject.AddComponent<AudioManager>();
        gameObject.AddComponent<UIManager>();
        gameObject.AddComponent<NetManager>();
        gameObject.AddComponent<CharacterManager>();
        gameObject.AddComponent<SceneMgr>();

        DontDestroyOnLoad(gameObject);
    }

    /// <summary>
    /// 发送消息 系统里面所有的发消息 都通过这个方法来发
    ///   根据不同的模块 来转发给 不同的模块 
    ///     通过 areaCode识别模块
    /// 
    ///     第二个参数:事件码 作用?用来区分 做什么事情的
    ///         比如说 第一个参数 识别到是角色模块 但是角色模块有很多功能 比如 移动 攻击 死亡 逃跑...
    ///             就需要第二个参数 来识别 具体是做哪一个动作
    /// </summary>
    public void Dispatch(int areaCode, int eventCode, object message)
    {
        switch (areaCode)
        {
            case AreaCode.AUDIO:
                AudioManager.Instance.Execute(eventCode, message);
                break;

            case AreaCode.CHARACTER:
                CharacterManager.Instance.Execute(eventCode, message);
                break;

            case AreaCode.NET:
                NetManager.Instance.Execute(eventCode, message);
                break;

            case AreaCode.GAME:
                break;

            case AreaCode.UI:
                UIManager.Instance.Execute(eventCode, message);
                break;

            case AreaCode.SCENE:
                SceneMgr.Instance.Execute(eventCode, message);
                break;

            default:
                break;
        }
    }
}

游戏的模块类:

/// <summary>
/// 区域码 代表 模块
/// </summary>
public class AreaCode
{
    /// <summary>
    /// UI模块
    /// </summary>
    public const int UI = 0;

    /// <summary>
    /// GAME模块
    /// </summary>
    public const int GAME = 1;

    /// <summary>
    /// CHARACTER模块
    /// </summary>
    public const int CHARACTER = 2;

    /// <summary>
    /// NET模块
    /// </summary>
    public const int NET = 3;

    /// <summary>
    /// AUDIO模块
    /// </summary>
    public const int AUDIO = 4;

    /// <summary>
    /// SCENE模块
    /// </summary>
    public const int SCENE = 5;

    //....

}

注册消息的类

/// <summary>
/// 每个模块的基类
///     1。保存自身注册的一系列消息
/// </summary>
public class ManagerBase : MonoBase
{

    /// <summary>
    /// 处理自身的消息
    /// </summary>
    /// <param name="eventCode">Event code.</param>
    /// <param name="message">Message.</param>
    public override void Execute(int eventCode, object message)
    {
        if (!dict.ContainsKey(eventCode))
        {
            Debug.LogWarning("没有注册 : " + eventCode);
            return;
        }

        //一旦注册过这个消息 给所有的脚本 发过去
        List<MonoBase> list = dict[eventCode];
        for (int i = 0; i < list.Count; i++)
        {
            list[i].Execute(eventCode, message);
        }
    }



    /// <summary>
    /// 存储 消息的事件码 和 哪个脚本 关联 的字典
    /// 
    /// 角色模块 有一个动作是 移动
    ///             移动模块需要关心这个事件 控制角色位置 进行移动
    ///             动画模块 也需要关心  控制角色播放动画    
    ///             音效模块 也需要关心  控制角色移动的音效播放 走路声
    /// </summary>
    private Dictionary<int,List<MonoBase>> dict = new Dictionary<int, List<MonoBase>>();

    /// <summary>
    /// 添加事件
    /// </summary>
    /// <param name="eventCode">Event code.</param>
    /// <param name="mono">Mono.</param>
    public void Add(int eventCode, MonoBase mono)
    {
        List<MonoBase> list = null;

        //之前没有注册过
        if (!dict.ContainsKey(eventCode))
        {
            list = new List<MonoBase>();
            list.Add(mono);
            dict.Add(eventCode, list);
            return;
        }

        //之前注册过
        list = dict[eventCode];
        list.Add(mono);
    }

    /// <summary>
    /// 添加多个事件
    ///     一个脚本关心多个事件
    /// </summary>
    /// <param name="eventCode">Event code.</param>
    public void Add(int[] eventCodes, MonoBase mono)
    {
        for (int i = 0; i < eventCodes.Length; i++)
        {
            Add(eventCodes[i], mono);
        }
    }


    /// <summary>
    /// 移除事件
    /// </summary>
    /// <param name="eventCode">Event code.</param>
    /// <param name="mono">Mono.</param>
    public void Remove(int eventCode, MonoBase mono)
    {
        //没注册过 没法移除 报个警告
        if (!dict.ContainsKey(eventCode))
        {
            Debug.LogWarning("没有这个事件" + eventCode + "注册");
            return;
        }

        List<MonoBase> list = dict[eventCode];

        if (list.Count == 1)
            dict.Remove(eventCode);
        else
            list.Remove(mono);
    }

    /// <summary>
    /// 移除多个
    /// </summary>
    /// <param name="eventCode">Event code.</param>
    /// <param name="mono">Mono.</param>
    public void Remove(int[] eventCodes, MonoBase mono)
    {
        for (int i = 0; i < eventCodes.Length; i++)
        {
            Remove(eventCodes[i], mono);
        }
    }

}

以上就完成了一个简单的消息收发机制的框架
下面来简单介绍一下用法,例如我们在开发UI模块儿的时候
需要一个UIBase 作为该模块的基类

public class UIBase : MonoBase
{
    /// <summary>
    /// 自身关心的消息集合
    /// </summary>
    private List<int> list = new List<int>();

    /// <summary>
    /// 绑定一个或多个消息
    /// </summary>
    /// <param name="eventCodes">Event codes.</param>
    protected void Bind(params int[] eventCodes)
    {
        list.AddRange(eventCodes);
        UIManager.Instance.Add(list.ToArray(), this);
    }

    /// <summary>
    /// 接触绑定的消息
    /// </summary>
    protected void UnBind()
    {
        UIManager.Instance.Remove(list.ToArray(), this);
        list.Clear();
    }

    /// <summary>
    /// 自动移除绑定的消息
    /// </summary>
    public  virtual void OnDestroy()
    {
        if (list != null)
            UnBind();
    }

    /// <summary>
    /// 发消息
    /// </summary>
    /// <param name="areaCode">Area code.</param>
    /// <param name="eventCode">Event code.</param>
    /// <param name="message">Message.</param>
    public void Dispatch(int areaCode, int eventCode, object message)
    {
        MsgCenter.Instance.Dispatch(areaCode, eventCode, message);
    }

    /// <summary>
    /// 设置面板显示
    /// </summary>
    /// <param name="active"></param>
    protected void setPanelActive(bool active)
    {
        gameObject.SetActive(active);
    }

}

单例UIManager负责消息的注册和移除 因为UIManager继承自ManagerBase

public class UIManager : ManagerBase 
{

    public static UIManager Instance = null;

    void Awake()
    {
        Instance = this;
    }
}

之后的有关UI操作都是在UIBase派生类上的开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yy763496668

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值