unity消息系统机制----个人学习记录

1.消息基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum CEventType
{
    GAME_OVER,
    GAME_WIN,
    PAUSE,
    GAME_DATA,
}

public class CBaseEvent
{

    protected Hashtable arguments;
    protected CEventType type;
    protected object sender;
    protected string eventName;

    public CEventType Type
    {
        get
        {
            return this.type;
        }
        set
        {
            this.type = value;
        }
    }

    public IDictionary Params
    {
        get
        {
            return this.arguments;
        }
        set
        {
            this.arguments = (value as Hashtable);
        }
    }

    public object Sender
    {
        get
        {
            return this.sender;
        }
        set
        {
            this.sender = value;
        }
    }

    public string EventName
    {
        get
        {
            return eventName;
        }

        set
        {
            eventName = value;
        }
    }

    public override string ToString()
    {
        return this.type + " { " + ((this.sender == null) ? "null" : this.sender.ToString()) + " } ";
    }
    
    public CBaseEvent Clone()
    {
        return new CBaseEvent(this.type, this.arguments, Sender);
    }

    public CBaseEvent(CEventType type, object sender)
    {
        this.Type = type;
        Sender = sender;
        if (this.arguments == null)
        {
            this.arguments = new Hashtable();
        }
    }

    public CBaseEvent(CEventType type, Hashtable args, object sender)
    {
        this.Type = type;
        this.arguments = args;
        Sender = sender;
        if (this.arguments == null)
        {
            this.arguments = new Hashtable();
        }
    }

    public CBaseEvent(string eventName, object sender)
    {
        this.EventName = eventName;
        Sender = sender;
        if (this.arguments == null)
        {
            this.arguments = new Hashtable();
        }
    }
}
2.封装对外使用的消息接口
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public delegate void CEventListenerDelegate(CBaseEvent evt);

public class CEventDispatcher
{

    static CEventDispatcher instance;
    public static CEventDispatcher GetInstance()
    {
        if (instance == null)
        {
            instance = new CEventDispatcher();
        }
        return instance;
    }

    private Hashtable listeners = new Hashtable();

    public void AddEventListener(CEventType eventType, CEventListenerDelegate listener)
    {
        CEventListenerDelegate ceventListenerDelegate = this.listeners[eventType] as CEventListenerDelegate;
        ceventListenerDelegate = (CEventListenerDelegate)Delegate.Combine(ceventListenerDelegate, listener);
        this.listeners[eventType] = ceventListenerDelegate;
    }

    public void RemoveEventListener(CEventType eventType, CEventListenerDelegate listener)
    {
        CEventListenerDelegate ceventListenerDelegate = this.listeners[eventType] as CEventListenerDelegate;
        if (ceventListenerDelegate != null)
        {
            ceventListenerDelegate = (CEventListenerDelegate)Delegate.Remove(ceventListenerDelegate, listener);
        }
        this.listeners[eventType] = ceventListenerDelegate;
    }

    public void AddEventListener(string eventName, CEventListenerDelegate listener)
    {
        CEventListenerDelegate ceventListenerDelegate = this.listeners[eventName] as CEventListenerDelegate;
        //这个combine就相当于委托的+=    (整体的实现就是类似于观察者模式)
        ceventListenerDelegate = (CEventListenerDelegate)Delegate.Combine(ceventListenerDelegate, listener);
        this.listeners[eventName] = ceventListenerDelegate;
    }

    /// <summary>
    /// 使用枚举传递
    /// </summary>
    /// <param name="evt"></param>
    public void DispatchEvent(CBaseEvent evt)
    {
        CEventListenerDelegate ceventListenerDelegate = this.listeners[evt.Type] as CEventListenerDelegate;

        if (ceventListenerDelegate != null)
        {
            try
            {
                ceventListenerDelegate(evt);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Concat(new string[] 
                {
                    "Error dispatching event ",
                    evt.Type.ToString(),
                    ": ",
                    ex.Message,
                    " ",
                    ex.StackTrace
                }), ex);
            }
        }
    }

    /// <summary>
    /// 使用字符串传递
    /// </summary>
    /// <param name="evt"></param>
    public void DispatchStringEvent(CBaseEvent evt)
    {
        CEventListenerDelegate ceventListenerDelegate = this.listeners[evt.EventName] as CEventListenerDelegate;

        if (ceventListenerDelegate != null)
        {
            try
            {
                ceventListenerDelegate(evt);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Concat(new string[]
                {
                    "Error dispatching event ",
                    evt.Type.ToString(),
                    ": ",
                    ex.Message,
                    " ",
                    ex.StackTrace
                }), ex);
            }
        }
    }

    public void RemoveAll()
    {
        this.listeners.Clear();
    }
}

3.开始使用

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 发送消息的一方
/// </summary>
public class PostBtn : MonoBehaviour
{
    public void OnBtn()
    {
        //第一个参数是事件的名称,第二个参数是传递的数值
        //CEventDispatcher.GetInstance().DispatchStringEvent(new CBaseEvent("开始触发", "这是重要数值"));
        CEventDispatcher.GetInstance().DispatchStringEvent(new CBaseEvent("TestMethod", Camera.main));
    }
}

4.接收方这边首先要在Start()的方法里面刚开始就要去监听这个消息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReceiveObject : MonoBehaviour {

    public void Start()
    {
        //消息机制,监听

        //第一个参数是事件名称,注意要与发送方的事件名称要一致,第二个是触发的方法MyTestFunc,
        //可以自定义,方法名随便写,注意必须有个CBaseEvent类型的参数
        CEventDispatcher.GetInstance().AddEventListener("TestMethod", CreateGoLobby);
    }
    public void CreateGoLobby(CBaseEvent evt)
    {
        print("我是参数" + evt);
    }
}

只要把上面的2个类拷贝到你的工程里面就可以用了

同时,除了支持 字符串类型的消息,还支持枚举类型的消息

已经在CBaseEvent.cs类的开头定义了枚举,把你的消息字符串,换成枚举就行了,因为我已经写好了重载方法,可以直接使用

猜你喜欢

转载自blog.csdn.net/Edision_li/article/details/81353397