Unity3D架构系列之- FSM有限状态机设计(二)

   在设计一中,我们把IState类设计了一下,接下来,我们写一下FiniteStateMachine这个类,这个类主要的作用就是对于外界调用,这个类是独立封装的,不继承Mono。这个类的功能是提供一个栈,用于存放FSState,还有通过Update进行状态的切换,以及对栈的管理,Pop和Push操作以及状态的注册。最重要的一点是声明了三个委托函数代码如下:

1
2
3
4
5
public delegate void EnterState(string stateName);
 
 public delegate void PushState(string stateName, string lastStateName);
 
 public delegate void PopState();

  主要是用于状态之间的切换。定义了Dictionary和Stack,前者用于State注册,后者是状态切换。代码如下:

1
2
3
protected Dictionary<string, FSState> mStates;
 
 protected Stack<FSState>    mStateStack;

  对应的相关处理函数如下:

1
2
3
4
5
6
7
8
9
public void Register(string stateName, IState stateObject) {
 
   if (mStates.Count == 0)
 
    mEntryPoint = stateName;
 
   mStates.Add(stateName, new FSState(stateObject, this, stateName, Enter, Push, Pop));
 
 }

用于状态机的注册,对Stack的操作是如下两个函数,一个是Pop,一个是Push函数。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public void Push(string newState) {
  string lastName = null;
  if (mStateStack.Count > 1) {
   lastName = mStateStack.Peek().StateName;
  }
  Push(newState, lastName);
 }
 protected void Push(string stateName, string lastStateName) {
  mStateStack.Push(mStates[stateName]);
  mStateStack.Peek().StateObject.OnEnter(lastStateName);
 }
 public void Pop() {
  Pop(null);
 }
 protected string Pop(string newName) {
  FSState lastState = mStateStack.Peek();
  string newState = null;
  if (newName == null && mStateStack.Count > 1) {
   int index = 0;
   foreach (FSState item in mStateStack) {
    if (index++ == mStateStack.Count - 2) {
     newState = item.StateName;
    }
   }
  }
  else {
   newState = newName;
  }
  string lastStateName = null;
  if (lastState != null) {
   lastStateName = lastState.StateName;
   lastState.StateObject.OnExit(newState);
  }
  mStateStack.Pop();
  return lastStateName;
 }

下面增加了状态触发消息事件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void Trigger(string eventName) {
  CurrentState.Trigger(eventName);
 }
 public void Trigger(string eventName, object param1) {
  CurrentState.Trigger(eventName, param1);
 }
  
 public void Trigger(string eventName, object param1, object param2) {
  CurrentState.Trigger(eventName, param1, param2);
 }
  
 public void Trigger(string eventName, object param1, object param2, object param3) {
  CurrentState.Trigger(eventName, param1, param2, param3);
 }
最后把FiniteStateMachine核心的功能给大家介绍完了,下面奉上整个类的代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class FiniteStateMachine {
 public delegate void EnterState(string stateName);
 public delegate void PushState(string stateName, string lastStateName);
 public delegate void PopState();
 protected Dictionary<string, FSState> mStates;
 protected string      mEntryPoint;
 protected Stack<FSState>    mStateStack;
 public FiniteStateMachine() {
  mStates = new Dictionary<string, FSState>();
  mStateStack = new Stack<FSState>();
  mEntryPoint = null;
 }
 public void Update() {
  if (CurrentState == null) {
   mStateStack.Push(mStates[mEntryPoint]);
   CurrentState.StateObject.OnEnter(null);
  }
  CurrentState.StateObject.OnUpdate();
 }
 public void Register(string stateName, IState stateObject) {
  if (mStates.Count == 0)
   mEntryPoint = stateName;
  mStates.Add(stateName, new FSState(stateObject, this, stateName, Enter, Push, Pop));
 }
 public FSState State(string stateName) {
  return mStates[stateName];
 }
 public void EntryPoint(string startName) {
  mEntryPoint = startName;
 }
 public FSState CurrentState { 
  get 
   if (mStateStack.Count == 0)
    return null;
   return mStateStack.Peek(); 
  } 
 }
 public void Enter(string stateName) {
  Push(stateName, Pop(stateName));
 }
 public void Push(string newState) {
  string lastName = null;
  if (mStateStack.Count > 1) {
   lastName = mStateStack.Peek().StateName;
  }
  Push(newState, lastName);
 }
 protected void Push(string stateName, string lastStateName) {
  mStateStack.Push(mStates[stateName]);
  mStateStack.Peek().StateObject.OnEnter(lastStateName);
 }
 public void Pop() {
  Pop(null);
 }
 protected string Pop(string newName) {
  FSState lastState = mStateStack.Peek();
  string newState = null;
  if (newName == null && mStateStack.Count > 1) {
   int index = 0;
   foreach (FSState item in mStateStack) {
    if (index++ == mStateStack.Count - 2) {
     newState = item.StateName;
    }
   }
  }
  else {
   newState = newName;
  }
  string lastStateName = null;
  if (lastState != null) {
   lastStateName = lastState.StateName;
   lastState.StateObject.OnExit(newState);
  }
  mStateStack.Pop();
  return lastStateName;
 }
 public void Trigger(string eventName) {
  CurrentState.Trigger(eventName);
 }
 public void Trigger(string eventName, object param1) {
  CurrentState.Trigger(eventName, param1);
 }
  
 public void Trigger(string eventName, object param1, object param2) {
  CurrentState.Trigger(eventName, param1, param2);
 }
  
 public void Trigger(string eventName, object param1, object param2, object param3) {
  CurrentState.Trigger(eventName, param1, param2, param3);
  }
}

上面整个FSMStateMachine类就封装完了,要知后事如何?且看系列三的讲解。

转自:http://jxwgame.blog.51cto.com/943299/1609539


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值