您的位置:首页 > 移动开发 > Unity3D

Unity3D有限状态机(FSM)学习笔记【6】Dispatcher类

2015-08-30 20:51 351 查看
本系列笔记转载自游戏蛮牛专栏作家Jackel的论坛文章,详细介绍了FSM的创建与使用,特与众分享。链接:http://www.manew.com/thread-37136-1-1.html

该类主要实现的是事件的注册、触发,以及分发Event消息。提供接口对外使用。使用了大量魔板函数。分发消息使用的队列方式,先进先出。代码如下:

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

namespace EventSystem
{

public class Dispatcher
{
public void Trigger( string eventName )
{
Call ( eventName, null, null, null );
}

public void Dispatch( string eventName )
{
Dispatched d = ( mFreeDispatch.Count == 0 ) ? new Dispatched() : mFreeDispatch.Pop();
mDispatched.Enqueue( d.Set( eventName ));
}

public int On( string eventName, Func<bool> action )
{
return Register ( eventName, delegate( object arg1, object arg2, object arg3 )
{
return ( action() );
});
}

public int On( string eventName, Action action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
action();
return true;
});
}

public void Trigger( string eventName, object param1 )
{
Call ( eventName, param1, null, null );
}

public void Dispatch( string eventName, object param1 )
{
Dispatched d = ( mFreeDispatch.Count == 0 ) ? new Dispatched() : mFreeDispatch.Pop();
mDispatched.Enqueue( d.Set( eventName, param1 ));
}

public int On<T>( string eventName, Func<T,bool> action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
T param1;
try{ param1 = (T)arg1; } catch { param1 = default(T); }
return ( action( param1 ));
});
}

public int On<T>( string eventName, Action<T> action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
T param1;
try { param1 = (T)arg1; } catch { param1 = default(T); }
action( param1 );
return true;
});
}

public void Trigger( string eventName, object param1, object param2 )
{
Call( eventName, param1, param2, null );
}

public void Dispatch( string eventName, object param1, object param2 )
{
Dispatched d = ( mFreeDispatch.Count == 0 ) ? new Dispatched() : mFreeDispatch.Pop();
mDispatched.Enqueue( d.Set( eventName, param1, param2 ));
}

public int On<T1,T2>( string eventName, Func<T1,T2,bool> action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
T1 param1;
T2 param2;
try { param1 = (T1)arg1; } catch { param1 = default(T1); }
try { param2 = (T2)arg2; } catch { param2 = default(T2); }
return ( action( param1, param2 ));
});
}

public int On<T1,T2>( string eventName, Action<T1,T2> action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
T1 param1;
T2 param2;
try { param1 = (T1)arg1; } catch { param1 = default(T1); }
try { param2 = (T2)arg2; } catch { param2 = default(T2); }
action( param1, param2 );
return true;
});
}

public void Trigger( string eventName, object param1, object param2, object param3 )
{
Call( eventName, param1, param2, param3 );
}

public void Dispatch( string eventName, object param1, object param2, object param3 )
{
Dispatched d = ( mFreeDispatch.Count == 0 ) ? new Dispatched() : mFreeDispatch.Pop();
mDispatched.Enqueue( d.Set( eventName, param1, param2, param3 ));
}

public int On<T1,T2,T3>( string eventName, Func<T1,T2,T3,bool> action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
T1 param1;
T2 param2;
T3 param3;
try{ param1 = (T1)arg1; } catch { param1 = default(T1); }
try{ param2 = (T2)arg2; } catch { param2 = default(T2); }
try{ param3 = (T3)arg3; } catch { param3 = default(T3); }
return ( action( param1, param2, param3 ) );
});
}

public int On<T1,T2,T3>( string eventName, Action<T1,T2,T3> action )
{
return Register( eventName, delegate( object arg1, object arg2, object arg3 )
{
T1 param1;
T2 param2;
T3 param3;
try{ param1 = (T1)arg1; } catch { param1 = default(T1); }
try{ param2 = (T2)arg2; } catch { param2 = default(T2); }
try{ param3 = (T3)arg3; } catch { param3 = default(T3); }
action( param1, param2, param3 );
return true;
});
}

public bool Cancel( int listenerID )
{
return mRegistered.Remove( listenerID );
}
public void DispatchPending()
{
while( mDispatched.Count > 0 )
{
Dispatched d = mDispatched.Dequeue();
Call( d.mEventName, d.mArg1, d.mArg2, d.mArg3 );
mFreeDispatch.Push( d );
}
}

int Register( string eventName, Func<object,object,object,bool> action )
{
int listenID = ++ mNextListenID;
Listen listen = ( mFreeListen.Count == 0 ) ? new Listen() : mFreeListen.Pop();
listen.mID = listenID;
listen.mAction = action;
mRegistered.Add( listenID, listen );
List<int> eventList;
if( !mRegisteredEvents.TryGetValue( eventName, out eventList ))
{
eventList = mRegisteredEvents[ eventName ] = new List<int>();
}
eventList.Add( listenID );
return listenID;
}

void Call( string eventName, object arg1, object arg2, object arg3 )
{
List<int> listenerList;
if( mRegisteredEvents.TryGetValue( eventName, out listenerList ))
{
for( int i = listenerList.Count - 1; i >= 0; --i )
{
Listen listener;
if( mRegistered.TryGetValue( listenerList[ i ], out listener ))
{
if( !listener.mAction( arg1, arg2, arg3 ))
{
mRegistered.Remove( listenerList[ i ] );
mFreeListen.Push( listener );
}
}
else
{
listenerList.RemoveAt( i );
}
}
if( listenerList.Count == 0 )
{
mRegisteredEvents.Remove( eventName );
}
}
}

class Listen
{
public int mID;
public Func<object,object,object,bool> mAction;
}

class Dispatched
{
public Dispatched Set( string eventName, object arg1 = null, object arg2 = null, object arg3 = null )
{
mEventName = eventName;
mArg1 = arg1;
mArg2 = arg2;
mArg3 = arg3;
return this;
}

public string mEventName;
public object mArg1, mArg2, mArg3;
}
Dictionary<string,List<int>> mRegisteredEvents = new Dictionary<string, List<int>>();
Dictionary<int, Listen> mRegistered = new Dictionary<int, Listen>();
Stack<Listen> mFreeListen = new Stack<Listen>();
Stack<Dispatched> mFreeDispatch = new Stack<Dispatched>();
Queue<Dispatched> mDispatched = new Queue<Dispatched>();
int mNextListenID = 4711;
}
}

一、事件注册与触发

在使用状态机是需先对消息事件注册,放到字典中保存

1、Register注册

按照事件名称,存放事件

2、Trigger触发

3、On

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity3d FSM