Unity基于“消息机制”的UI框架(实体项目讲解)

1.效果展示。

Unity基于“消息机制”的UI框架(实体项目讲解)_第1张图片

2.代码结构

Unity基于“消息机制”的UI框架(实体项目讲解)_第2张图片

这里定义了一个StartPanel(开始界面),LoginPanel(登录界面),RegisterPanel(注册界面)

Unity基于“消息机制”的UI框架(实体项目讲解)_第3张图片

Framework文件夹:包含了框架所包含的工具类。UI文件夹:项目的界面操作文件。

上代码:

void Awake() {
        //注册绑定事件。
        Bind(UIEvent.BEGIN_PANEL_ACTIVE);
        
    }

首先LoginPanel:先注册绑定“UIEvent.BEGIN_PANEL_ACTIVE”显示登录界面,

/// 
    /// 自身关心的消息集合
    /// 
    private List list = new List();

    /// 
    /// 绑定一个或多个消息
    /// 
    /// Event codes.
    /// params int [] eventCodes :可以接收多个参数。
    protected void Bind(params int[] eventCodes)
    {
        list.AddRange(eventCodes);
        //List.ToArray(); 将集合元素复制到新数组中。
        UIManager.Instance.Add(list.ToArray(), this);
    }

Uibase调用Bind方法绑定一个或者多个消息(一个界面代码模块可以绑定多个事件),将事件ID,添加到消息集合中。在上传给Uimanager的Add方法。


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

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

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

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

Add方法依次对该脚本所关注的所有事件进行注册(一个脚本模块可以关注多个事件),


接受响应

public class StartPanel : UIBase {

    private Button beginBtn;
    private Button registerBtn;
	// Use this for initialization
	void Start () {
        beginBtn = transform.Find("beginBtn").GetComponent

beginClick函数接收登录按钮的点击事件,调用UIBase的Dispatch方法,向UIbase发送"显示登录界面" 的消息,


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

    /// 
    /// 绑定一个或多个消息
    /// 
    /// Event codes.
    /// params int [] eventCodes :可以接收多个参数。
    protected void Bind(params int[] eventCodes)
    {
        list.AddRange(eventCodes);
        //List.ToArray(); 将集合元素复制到新数组中。
        UIManager.Instance.Add(list.ToArray(), this);
    }

    /// 
    /// 解除绑定的消息
    /// 
    protected void UnBind()
    {
        UIManager.Instance.Remove(list.ToArray(), this);
        list.Clear();
    }

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

    /// 
    /// 发消息
    /// 
    /// Area code.
    /// Event code.
    /// Message.
    public void Dispatch(int areaCode, int eventCode, object message)
    {
        //uibase传递给MsgCenter消息处理中心
        MsgCenter.Instance.Dispatch(areaCode, eventCode, message);
    }

    /// 
    /// 设置面板显示和隐藏。
    /// 
    /// 
    protected void setPanelActive(bool active)
    {
        gameObject.SetActive(active);
    }

}

UIbase的Dispatch方法,在把“显示登录界面”的请求,传递给MsgCenter(消息处理中心)


 /// 
    /// 发送消息 系统里面所有的发消息 都通过这个方法来转发
    ///   怎么转发?根据不同的模块 来发给 不同的模块 
    ///     怎么识别模块呢?通过 areaCode
    /// 
    ///     第二个参数:事件码 作用?用来区分 做什么事情的
    ///         比如说 第一个参数 识别到是角色模块 但是角色模块有很多功能 比如 移动 攻击 死亡 逃跑...
    ///             就需要第二个参数 来识别 具体是做哪一个动作
    ///     Dispatch调遣,分派。
    /// 
    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.GAME:
                break;

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

            default:
                break;
        }
    }

MsgCenter(消息处理中心):调用Dispatch方法,发送给ManagerBase的Execute方法。


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

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

ManagerBase的Execute方法,分配下发给各个界面,让界面处理自身的消息。(注意:一个消息可以被多个脚本所响应

void Awake() {
        //注册绑定事件。
        Bind(UIEvent.BEGIN_PANEL_ACTIVE);
        
    }

    public override void Execute(int eventCode, object message)
    {
        switch(eventCode){
            case UIEvent.BEGIN_PANEL_ACTIVE:
                setPanelActive((bool)message);
                break;
            default:
                break;
        }
        base.Execute(eventCode, message);
    }

因为LoginPanel:里面绑定注册了“UIEvent.BEGIN_PANEL_ACTIVE” 事件,则会执行Execute方法,进行响应。显示登录界面。

 到这来,我们就完成从注册事件,到响应事件的功能。

要注意我们这个基于消息机制的UI框架,一个事件可以被多个界面代码模块所响应,同时一个界面代码模块,也可以注册绑定多个事件。(要先注册绑定,才会有响应)

优点:降低了各模块之间的耦合度并减少代码对组件的依赖,可以自动的添加和删除组件,方便用AssetBundle进行加载资源,不会出现代码,组件丢失。



你可能感兴趣的:(Unity基于“消息机制”的UI框架(实体项目讲解))