参考自这2片文章:
https://blog.csdn.net/ff_0528/article/details/79165272 简单易懂
https://www.cnblogs.com/u3ddjw/p/6826921.html#_label0 比上一篇复杂一点点,写的很好
委托与事件:委托可以在本类或者其他类注册函数,执行函数。事件可以在本类或者其他类注册函数,但只能在本类中执行函数。
继承自MonoBehaviour的函数不能new出对象,所以相关的类都没有继承自MonoBehaviour。
主要包含以下几个类:
枚举类型:发送的是哪种类型的消息,某种类型的消息事件可以有多个(委托链)。
消息类:要发送的消息。
发送消息的类:达到条件,触发发送消息的事件,使用 “消息中心类“ 发送消息。
注册消息的类:需要提前向“消息中心类注册事件”,然后等待接受消息,做出回应。
消息中心类:被 “发送消息的类“ 调用,做出判断,将消息发动到 “注册消息的类” 那里。
思考:我们要达到的效果其实就是“发送消息的类“发送消息,“注册消息的类”做出回应。
不使用消息机制:直接在“发送消息的类“里面创建“注册消息的类”的对象,然后调用其函数就行了。
使用消息机制:即“发送消息的类“与“注册消息的类”之间加了一个 “消息中心类“作为中间人。
以下是超级简单的版本:
发送消息的类:达到条件,触发发送消息的事件,使用 “消息中心类“ 发送消息。
using UnityEngine;
public class SimpleSender : MonoBehaviour {
void Start () {
//使用消息机制
SimpleInfoCenter.Instance.CallFun(SimpleType.TypeOne,new SimpleInfo(1001,new GameObject("XiaoMing")));
//不使用消息机制
//SinpleReceive receive = new SinpleReceive();//这里使用GetComponent<>()或者GameObject.Find()来拿到对象
//receive.Fun(new SimpleInfo(1001, new GameObject("XiaoMing")));
}
}
注册消息的类:需要提前向“消息中心类注册事件”,然后等待接受消息,做出回应。
using UnityEngine;
public class SinpleReceive : MonoBehaviour {
void Awake () {
SimpleInfoCenter.Instance.AddFun(SimpleType.TypeOne,Fun);//使用消息机制
}
public void Fun(SimpleInfo info)
{
print("info.id " + info.id);
print("info.obj.name " + info.obj.name);
}
}
消息中心类:被 “发送消息的类“ 调用,做出判断,将消息发动到 “注册消息的类” 那里。
using System.Collections.Generic;
using UnityEngine;
public enum SimpleType 枚举类型:发送的是哪种类型的消息,某种类型的消息事件可以有多个(委托链)。
{
TypeOne,TypeTwo
}
public class SimpleInfo 消息类:要发送的消息。
{
public int id;
public GameObject obj;
public SimpleInfo(int id,GameObject obj)
{
this.id = id;
this.obj = obj;
}
}
public class SimpleInfoCenter { 消息中心类:被 “发送消息的类“ 调用,做出判断,将消息发动到 “注册消息的类” 那里。
public delegate void SimpleFun(SimpleInfo info);
public static SimpleInfoCenter Instance = new SimpleInfoCenter();
private Dictionary
public void AddFun(SimpleType type,SimpleFun fun)
{
dic[type] = fun;
}
public void CallFun(SimpleType type, SimpleInfo info)
{
dic[type](info);
}
}
以下是比较完整的版本,代码如下:
消息类:要发送的消息。
public class Notification {
public GameObject sender;
public EventArgs param;
public Notification()
{
}
public Notification(EventArgs param)
{
this.sender = null;
this.param = param;
}
public Notification(GameObject sender,EventArgs param)
{
this.sender = sender;
this.param = param;
}
}
//这个地方不清楚为什么要这样写
public class EventArgsTest : EventArgs
{
public int id;
public string name;
public EventArgsTest(int id,string name)
{
this.id = id;
this.name = name;
}
}
发送消息的类:达到条件,触发发送消息的事件,使用 “消息中心类“ 发送消息。
using System;
using UnityEngine;
public class Send : MonoBehaviour {
// Use this for initialization
void Start () {
times = 0;
}
int times;
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Q) && times == 0)
{
times = 1;
NotificationCenter.Get().PostDispatchEvent((int)ENotificationMsgType.ELoadResProgress, new Notification(new EventArgsTest(1001, "kkkk")));
}
else if(Input.GetKeyUp(KeyCode.Q))
times = 0;
}
}
注册消息的类:需要接受消息的类。
using UnityEngine;
public class Receive : MonoBehaviour {
// Use this for initialization
void Awake () {
NotificationCenter.Get().AddEventListener((int)ENotificationMsgType.ELoadResProgress, MyFun);
}
void OnDestroy()
{
NotificationCenter.Get().ERemoveEventListener((int)ENotificationMsgType.ELoadResProgress, MyFun);
print(" destroy ");
}
void MyFun(Notification notification)
{
print(" receive "+((EventArgsTest)notification.param).id);
}
}
枚举类型:发送的是哪种类型的消息,某种类型的消息事件可以有多个(委托链)。
public enum ENotificationMsgType // 消息发送的枚举值,应该转为uint型
{
ENull = 0, //Test
ELoadResProgress = 1,
}
消息中心类:被 “发送消息的类“ 调用,做出判断,将消息发动到 “注册消息的类” 哪里。
public class NotificationCenter
{
private static NotificationCenter instance = null;
public static NotificationCenter Get()
{
if (instance == null)
instance = new NotificationCenter();
return instance;
}
public delegate void NotificationDelegate(Notification notific);
private Dictionary
public bool HasEventListener(uint eventKey)
{
if (eventListeners.ContainsKey(eventKey))
return true;
return false;
}
public void AddEventListener(uint eventKey, NotificationDelegate listener)
{
if (!HasEventListener(eventKey))
eventListeners[eventKey] = listener;
else
eventListeners[eventKey] += listener;
}
public void ERemoveEventListener(uint eventKey)
{
eventListeners.Remove(eventKey);
}
public void ERemoveEventListener(uint eventKey, NotificationDelegate listener)
{
if (!HasEventListener(eventKey))
return;
eventListeners[eventKey] -= listener;
if (eventListeners[eventKey] == null)
ERemoveEventListener(eventKey);
}
public void PostDispatchEvent(uint eventKey,Notification notific)
{
if (!HasEventListener(eventKey))
return;
eventListeners[eventKey](notific);
}
public void PostDispatchEvent(uint eventKey, GameObject sender, EventArgs param)
{
if (!HasEventListener(eventKey))
return;
eventListeners[eventKey](new Notification(sender, param));
}
public void PostDispatchEvent(uint eventKey, EventArgs param)
{
if (!HasEventListener(eventKey))
return;
eventListeners[eventKey](new Notification(param));
}
}