using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum CEventType //事件类型,最好放在单独的脚本中
{
GAME_OVER,
GAME_WIN,
PAUSE,
ENERGY_EMEPTY,
GAME_DATA,
}
public class CBaseEvent {
protected Hashtable arguments; //哈希表用来存储委托事件
protected CEventType type; //事件类型
protected Object sender; //存储事件分发的对象
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 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;
this.sender = sender;
if(this.arguments==null)
{
arguments = new Hashtable();
}
}
public CBaseEvent(CEventType type,Hashtable args,Object sender)
{
this.type = type;
this.arguments = args;
this.sender = sender;
if(this.arguments==null)
{
this.arguments = new Hashtable();
}
}
}
事件的监听和分发接口封装在游戏逻辑中经常呗调用,同时也是对外提供的接口:
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 cEventDelegate = this.listeners[eventType] as CEventListenerDelegate;
cEventDelegate = (CEventListenerDelegate)Delegate.Combine(cEventDelegate, listener);
//上面相当于 //cEventDelegate += listener;
this.listeners[eventType] = cEventDelegate;
}
public void RemoveEventListener(CEventType eventType,CEventListenerDelegate listener)
{
CEventListenerDelegate cEventDelegate = this.listeners[eventType] as CEventListenerDelegate;
if(cEventDelegate!=null)
{
cEventDelegate = (CEventListenerDelegate)Delegate.Remove(cEventDelegate,listener);
//上面相当于 //cEventDelegate -= listener;
}
this.listeners[eventType] = cEventDelegate;
}
public void DispatchEvent(CBaseEvent evt) //触发函数
{
CEventListenerDelegate cEventDelegate = this.listeners[evt.Type] as CEventListenerDelegate;
if(cEventDelegate!=null)
{
try
{
cEventDelegate(evt); //内置触发函数
}
catch(System.Exception e)
{
throw new System.Exception(string.Concat(new string[]
{
"Error dispathcing event",
evt.Type.ToString(),
":",
e.Message,
" ",
e.StackTrace
}),e);
}
}
}
public void RemoveAll()
{
this.listeners.Clear();
}
}
CEventDispatcher.GetInstance().AddEventListener(CEventType.GAME_WIN, NumberListener);//添加监听事件
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.GAME_WIN, this)); //触发NumberListener函数
public class CEventDelegateExample : MonoBehaviour {
void Start () {
CEventDispatcher.GetInstance().AddEventListener(CEventType.GAME_WIN, NumberListener);//添加监听事件
}
void Update () {
if(Input.GetMouseButtonDown(0))
{
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.GAME_WIN, this)); //如果按下鼠標左键,触发NumberListener函数
}
}
void OnDestroy()
{
CEventDispatcher.GetInstance().RemoveEventListener(CEventType.GAME_WIN, NumberListener);
}
public void NumberListener(CBaseEvent evt)
{
Debug.Log("Mouse Down");
}
}
下面尝试用Lua来实现事件的监听与触发
GlobalListenerMap = { ---所有事件存储表
--[[
[target] = {
[type#key] = listenerList,
}
--]]
}
local cacheEventTypeKey = {--所有的type#key存储表
--[eventType] = { count, keyvalue}
}
local GlobalObserver = false
function GetGlobalObserver()
return GlobalObserver
end
local GlobalTarget = false
function GetGlobalTarget()
return GlobalTarget
end
----------------------------------------------------
local function genIndex(eventType,key) --生成type#key,作为target中的事件列表的索引
local eventTypeMap=cacheEventTypeKey[eventType]
if not eventTypeMap then
local f = string.format("%s#%s", eventType, tostring(key))
local keyValue={}
keyValue[tostring(key)]=f
eventTypeMap={}
eventTypeMap._KeyCount=1 --计数
eventTypeMap._KeyValue = keyValue
cacheEventTypeKey[eventType] = eventTypeMap
return f
end
local keyValue=eventTypeMap._KeyValue
local f=keyValue[tostring(key)]
if f then
return f
end
local keyCount=eventTypeMap._KeyCount+1
if keyCount>1000 then
keyValue = {}
keyCount=1
eventTypeMap._KeyValue=keyValue
end
eventTypeMap._KeyCount=keyCount --计数
f=string.format("%s#%s", eventType, tostring(key))
keyValue[tostring(key)]=f
eventTypeMap._KeyValue = keyValue
return f
end
local nextListenerId = 0
local function genListenerId()
nextListenerId = nextListenerId + 1
return nextListenerId
end
-------------------事件监听处理器---------------------------------
local cListener={}
local cListenerMeta={__index=cListener}
function cListener.Create(observer,target,type,key,callback)
local OId=genListenerId()
local typeKeyIndex=genIndex(type,key)
local listener = {
observer,
target,
type,
key,
callback,
typeKeyIndex,
OId,
}
setmetatable(listener,cListenerMeta)
local targetListenerList=GetTargetListenerList(target,typeKeyIndex)
table.insert(targetListenerList,listener)
if IsTable(observer) then---绑定在监听者上,在监听者release时便于删除事件
local objListenerMap = GetSubTableWithDefault(observer, "__eventListenerMap")
objListenerMap[OId] = listener
end
return listener
end
function cListener:Remove()
local typeIndex=self:GetTypeKey()
if not typeIndex then
return
end
self[6]=nil
local observer=self:GetObserver()
if IsTable(observer) then
local OId=self:GetObserLisID()
observer.__eventListenerMap[OId]=nil
end
local target = self:GetTarget()
local typeListenerMap = GlobalListenerMap[target]
if not typeListenerMap then
return
end
local listenerList = typeListenerMap[typeIndex]
local len = #listenerList
if len == 1 and listenerList[1] == self then
listenerList[1] = nil
typeListenerMap[typeIndex] = nil
if next(typeListenerMap,nil) then
GlobalListenerMap[target] = nil
end
else
local key = table.member_key(listenerList, self) --- O(N)
if key then
----使用最后一个元素覆盖并删除最后一个元素
listenerList[key] = listenerList[len]
listenerList[len] = nil
end
end
end
function cListener:GetObserver() return self[1] end
function cListener:GetTarget() return self[2] end
function cListener:GetType() return self[3] end
function cListener:GetKey() return self[4] end
function cListener:GetCallBack() return self[5] end
function cListener:GetTypeKey() return self[6] end
function cListener:GetObserLisID() return self[7] end
function cListener:toString()
local str=self:GetTarget()..":"..genIndex(self:GetType(),self:GetKey())
return str
end
function cListener:Handle(event)
-- print("Handle this event",self:toString())
local callback = self:GetCallBack()
xpcall(callback,
function()
print(self:toString()..":Handle error")
end,
event)
end
--------------------------事件--------------------------------
local cEvent={}
function cEvent.Create(target, type, key, data)
local event = {
target,
type,
key,
data,
}
setmetatable(event, {__index=cEvent})
return event
end
function cEvent:GetTarget() return self[1] end
function cEvent:GetType() return self[2] end
function cEvent:GetKey() return self[3] end
function cEvent:GetData() return self[4] end
----------------------------------------------------------
function GetSubTableWithDefault(target,key)
local value=target[key]
if not value then
value={}
target[key]=value
end
return value
end
function GetTargetListenerList(target,typeKeyIndex)
local targetMap=GetSubTableWithDefault(GlobalListenerMap,target)
local listenerList=GetSubTableWithDefault(targetMap,typeKeyIndex)
return listenerList
end
function AddEventListener(observer,target,type,key,callback)
local listener=cListener.Create(observer,target,type,key,callback)
return listener
end
function RemoveEventListener(listener)
if listener then
listener:Remove()
end
end
---移除自己监听别人的
function RemoveAllEventListener(observer)
if not IsTable(observer.__eventListenerMap) then return end
for _, listener in pairs(observer.__eventListenerMap) do
listener:Remove()
end
observer.__eventListenerMap = nil
end
function RemoveEventListener(observer,target,type,key)
local toDelListenerList={}
local typeKeyIndex=genIndex(type, key)
local typeListenerMap = GlobalListenerMap[target]
if not typeListenerMap then
return
end
local listenerList = typeListenerMap[typeKeyIndex]
if not listenerList then
return
end
for _, listener in pairs(listenerList) do
if IsTable(observer) then
if listener:GetObserver() == observer then
table.insert( toDelListenerList, listener)
end
else
table.insert( toDelListenerList, listener)
end
end
for _, listener in ipairs(toDelListenerList) do
listener:Remove()
end
end
---事件触发
function DispatchEvent(target,type,key,data)
local event=cEvent.Create(target,type,key,data)
local typeKeyIndex=genIndex(type,key)
local targetListenerList=GetTargetListenerList(target,typeKeyIndex)
for _, listener in pairs(targetListenerList) do
listener:Handle(event)
end
end
function __init__(module, updated)
GlobalObserver = clsObject:New()
GlobalTarget = clsObject:New()
end