观察者类
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Notification
{
public GameObject sender;
public object param;
public Notification(
object param,GameObject sender =
null)
{
this.sender = sender;
this.param = param;
}
public override string ToString()
{
return string.Format(
"sender={0},param={1}",
this.sender,
this.param);
}
}
public class NotificationCenter {
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)
{
listNoti.Add(it.Value);
}
else
{
listRemoveKey.Add(it.Key);
}
}
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));
}
}
}
public bool HasEventListener(
string eventKey)
{
return m_dicEvent.ContainsKey(eventKey);
}
}
使用:
订阅消息与取消订阅消息
void EventInit()
{
NotificationCenter.Get().ObjAddEventListener(KEventKey.m_evOpenInputTip, gameObject, OnEventOpenInputTip);
}
private void OnDestroy()
{
NotificationCenter.Get().ObjRemoveEventListener(KEventKey.m_evOpenInputTip, gameObject);
}
void OnEventOpenInputTip(Notification param)
{
}
发布消息
NotificationCenter
.Get()
.ObjDispatchEvent(KEventKey
.m_evDown,
1)
注意的地方1
lock (m_dicEvent)
{
foreach (
var it
in m_dicEvent[eventKey])
{
if (it.Key !=
null)
{
listNoti.Add(it.Value);
}
else
{
listRemoveKey.Add(it.Key);
}
}
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。先保存一遍要处理的消息,因为有些委托是创建对象,如果对象初始化执行
public void Awake()
{
SetExamJianXiuDian()
for (int i =
0
{
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
void OnEvNext(Notification noti)
{
if (gameObject.activeSelf ==
true)
ChallengeMgr.m_instance.OnNextRet(GetScore());
}
当执行委托时,要判断下这个脚本的GameObject是否激活状态,再去执行委托,不然出现一些难以确定bug