Unity3D架构系列之- FSM有限状态机设计五

原文:http://www.manew.com/thread-37894-1-1.html


在设计五中,我们把事件系统EventSystem实现一下。这个EventSystem类主要实现的是事件的注册,触发,以及分发Event消息的作用。提供接口对外使用的。在这里面为了功能扩展方便用了好多模板函数,方便大家调用。

         分发消息的时候,我们采用的是队列的方式,就是先进先出原则。

        首先要把消息事件注册一下,就是将其放到我们预先定义的表里面。函数代码如下所示:


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;
                }
接下来就是 消息事件的触发代码如下:

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

               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, out listener)) {
                                 if(!listener.mAction(arg1, arg2, arg3)) {
                                  mRegistered.Remove(listenerList);
                                 mFreeListen.Push(listener);
                                listenerList.RemoveAt(i);
                                    }
                          }
                        else {
                                          listenerList.RemoveAt(i);
                               }
                       }
                   if(listenerList.Count == 0) {
                    mRegisteredEvents.Remove(eventName);
                              }
                   }
                }
遍历查找消息列表是否在mRegistererdEvents这个字典里面,mRegisteredEvents的定义如下:
Dictionary<string,List<int>>  mRegisteredEvents = new Dictionary<string, List<int>>();
       Listen的定义如下:
      class Listen {
              public int mID;
             public Func<object,object,object,bool> mAction;
          }
接下来就是最核心的功能了,状态机的切换功能代码:
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;
                        });
         }
整个的EventSystem事件系统的代码如下所示:
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);
                                                        listenerList.RemoveAt(i);
                                                }
                                        }
                                        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;
        }
}

接下来我会在最后一讲也就是设计六中,给大家说一下如何去使用。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值