观察者类
代码语言:javascript复制using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Notification
{
/// <summary>
/// 通知发送者
/// </summary>
public GameObject sender;
/// <summary>
/// 通知内容
/// 备注:在发送消息时需要装箱、解析消息时需要拆箱
/// </summary>
public object param;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="param"></param>
public Notification(object param,GameObject sender = null)
{
this.sender = sender;
this.param = param;
}
/// <summary>
/// 实现ToString方法
/// </summary>
/// <returns></returns>
public override string ToString()
{
return string.Format("sender={0},param={1}", this.sender, this.param);
}
}
public class NotificationCenter {
/// <summary>
/// 通知中心单例
/// </summary>
private static NotificationCenter instance = null;
public delegate void OnNotification(Notification notific);
public static NotificationCenter Get()
{
if (instance == null)
{
instance = new NotificationCenter();
return instance;
}
return instance;
}
//实现一对多的消息
private Dictionary<string, Dictionary<GameObject, OnNotification>> m_dicEvent
= new Dictionary<string, Dictionary<GameObject, OnNotification>>();
public void ObjAddEventListener(string eventKey, GameObject obj,OnNotification eventListener)
{
if (!m_dicEvent.ContainsKey(eventKey))
{
Dictionary<GameObject, OnNotification> dic = new Dictionary<GameObject, OnNotification>();
dic[obj] = eventListener;
m_dicEvent[eventKey] = dic;
}
else
{
m_dicEvent[eventKey][obj] = eventListener;
}
}
public void ObjRemoveEventListener(string eventKey,GameObject obj)
{
if (!m_dicEvent.ContainsKey(eventKey))
return;
m_dicEvent[eventKey].Remove(obj);
}
public void ObjDispatchEvent(string eventKey, object param = null,GameObject sender = null)
{
if (!m_dicEvent.ContainsKey(eventKey))
return;
List<GameObject> listRemoveKey = new List<GameObject>();
List<OnNotification> listNoti = new List<OnNotification>();
lock (m_dicEvent)
{
foreach (var it in m_dicEvent[eventKey])
{
if (it.Key != null)
{
//it.Value(new Notification(param, sender));
listNoti.Add(it.Value);
}
else
{
listRemoveKey.Add(it.Key);
}
}
//删除已经Destory的GameObject
for (int i = 0; i < listRemoveKey.Count; i )
{
m_dicEvent[eventKey].Remove(listRemoveKey[i]);
}
for ( int i = 0; i < listNoti.Count; i )
{
listNoti[i](new Notification(param, sender));
}
}
}
/// <summary>
/// 是否存在指定事件的监听器
/// </summary>
public bool HasEventListener(string eventKey)
{
return m_dicEvent.ContainsKey(eventKey);
}
}
使用:
订阅消息与取消订阅消息
代码语言:javascript复制 void EventInit()
{
NotificationCenter.Get().ObjAddEventListener(KEventKey.m_evOpenInputTip, gameObject, OnEventOpenInputTip);
}
private void OnDestroy()
{
NotificationCenter.Get().ObjRemoveEventListener(KEventKey.m_evOpenInputTip, gameObject);
}
void OnEventOpenInputTip(Notification param)
{
}
发布消息
代码语言:javascript复制 NotificationCenter.Get().ObjDispatchEvent(KEventKey.m_evDown, 1);
注意的地方1
代码语言:javascript复制lock (m_dicEvent)
{
foreach (var it in m_dicEvent[eventKey])
{
if (it.Key != null)
{
//it.Value(new Notification(param, sender));
listNoti.Add(it.Value);
}
else
{
listRemoveKey.Add(it.Key);
}
}
//删除已经Destory的GameObject
for (int i = 0; i < listRemoveKey.Count; i )
{
m_dicEvent[eventKey].Remove(listRemoveKey[i]);
}
for ( int i = 0; i < listNoti.Count; i )
{
listNoti[i](new Notification(param, sender));
}
}
发出消息时,1.根据GameObject是否存在,删除对应消息表中。 2。先保存一遍要处理的消息,因为有些委托是创建对象,如果对象初始化执行
代码语言:javascript复制 public void Awake()
{
SetExamJianXiuDian();
for (int i = 0; i < m_listId.Count; i )
{
m_dicId[m_listId[i]] = false;
}
NotificationCenter.Get().ObjAddEventListener(KEventKey.m_evExamJianXiuDian, gameObject, OnEvJianXiuDian);
NotificationCenter.Get().ObjAddEventListener(KEventKey.m_evChallengeCommit, gameObject, OnEvCommit);
NotificationCenter.Get().ObjAddEventListener(KEventKey.m_evChallengeNext, gameObject, OnEvNext);
}
就会产生执行委托,边遍历字典边修改字典问题
注意的地方2
代码语言:javascript复制 void OnEvNext(Notification noti)
{
if (gameObject.activeSelf == true)
ChallengeMgr.m_instance.OnNextRet(GetScore());
}
当执行委托时,要判断下这个脚本的GameObject是否激活状态,再去执行委托,不然出现一些难以确定bug