开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

教程分享

关注:559

当前位置:游戏蛮牛 技术专区 教程分享

查看: 347|回复: 0

[基础知识] Unity有限状态机实现

[复制链接]  [移动端链接]
7日久生情
3226/5000
排名
2617
昨日变化
1

1254

主题

1255

帖子

3226

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
132510
好友
17
蛮牛币
20065
威望
0
注册时间
2015-12-24
在线时间
244 小时
最后登录
2017-1-20
发表于 2016-7-5 10:58:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
  有限状态机主要是用于状态之间的切换,状态之间的切换也可以通过Switch Case或者if else实现。由于使用二者实现主要是对用用户扩展不是很方便,所以就有了有限状态机的概念。 有限状态机主要是用于不同的状态频繁的切换。那在Unity中我们如何定义有限状态机?其实有限状态机主要包括三部分,切换状态,进入状态,退出状态。接下来我们就利用Unity实现有限状态机并给大家展示如何应用。

  首先我们定义FSMState.cs脚本,我们通过委托对函数状态进行切换.代码如下:

  using System;

  using System.Collections.Generic;

  namespace FSM

  {

  public class FSMState

  {

  private int stateName;

  private Dictionary<int, int> transitions = new Dictionary<int, int>();

  //设置状态名字

  public void SetStateName(int newStateName)

  {

  this.stateName = newStateName;

  }

  //获取状态名字

  public int GetStateName()

  {

  return this.stateName;

  }

  //加入状态

  public void AddTransition(int transition, int outputState)

  {

  this.transitions[transition] = outputState;

  }

  //使用状态

  public int ApplyTransition(int transition)

  {

  int result = this.stateName;

  if (this.transitions.ContainsKey(transition))

  {

  result = this.transitions[transition];

  }

  return result;

  }

  }

  }

  以上的类定义的是状态。下面我们定义对外接口,有限状态机FStateMachine.cs脚本

  using System;

  using System.Collections;

  using System.Collections.Generic;

  using System.Threading;

  namespace FSM

  {

  public class FStateMachine

  {

  //声明了一个委托用于状态之间的切换

  public delegate void OnStateChangeDelegate(int fromStateName, int toStateName);

  private List<FSMState> states = new List<FSMState>();

  private volatile int currentStateName;

  public FiniteStateMachine.OnStateChangeDelegate onStateChange;

  private object locker = new object();

  //增加状态

  public void AddState(object st)

  {

  int stateName = (int)st;

  FSMState fSMState = new FSMState();

  fSMState.SetStateName(stateName);

  this.states.Add(fSMState);

  }

  //增加所有状态

  public void AddAllStates(Type statesEnumType)

  {

  IEnumerator enumerator = Enum.GetValues(statesEnumType).GetEnumerator();

  try

  {

  while (enumerator.MoveNext())

  {

  object current = enumerator.Current;

  this.AddState(current);

  }

  }

  finally

  {

  IDisposable disposable;

  if ((disposable = (enumerator as IDisposable)) != null)

  {

  disposable.Dispose();

  }

  }

  }

  //该函数是表示从from到to的转换

  public void AddStateTransition(object from, object to, object tr)

  {

  int num = (int)from;

  int outputState = (int)to;

  int transition = (int)tr;

  FSMState fSMState = this.FindStateObjByName(num);

  fSMState.AddTransition(transition, outputState);

  }

  public int ApplyTransition(object tr)

  {

  object obj = this.locker;

  Monitor.Enter(obj);

  int result;

  try

  {

  int transition = (int)tr;

  int num = this.currentStateName;

  this.currentStateName = this.FindStateObjByName(this.currentStateName).ApplyTransition(transition);

  if (num != this.currentStateName)

  {

  if (this.onStateChange != null)

  {

  this.onStateChange(num, this.currentStateName);

  }

  }

  result = this.currentStateName;

  }

  finally

  {

  Monitor.Exit(obj);

  }

  return result;

  }

  public int GetCurrentState()

  {

  object obj = this.locker;

  Monitor.Enter(obj);

  int result;

  try

  {

  result = this.currentStateName;

  }

  finally

  {

  Monitor.Exit(obj);

  }

  return result;

  }

  public void SetCurrentState(object state)

  {

  int toStateName = (int)state;

  if (this.onStateChange != null)

  {

  this.onStateChange(this.currentStateName, toStateName);

  }

  this.currentStateName = toStateName;

  }

  private FSMState FindStateObjByName(object st)

  {

  int num = (int)st;

  FSMState result;

  foreach (FSMState current in this.states)

  {

  if (num.Equals(current.GetStateName()))

  {

  result = current;

  return result;

  }

  }

  result = null;

  return result;

  }

  }

  }

  以上定义的是有限状态机类,那接下来我给大家展示如何实现。

  我们可以先初始化状态,那如何初始化,看下面的函数:

  private void InitStates()

  {

  this.fsm = new FStateMachine();

  this.fsm.AddAllStates(typeof(TCPSocketLayer.States));

  this.fsm.AddStateTransition(TCPSocketLayer.States.Disconnected, TCPSocketLayer.States.Connecting, TCPSocketLayer.Transitions.StartConnect);

  this.fsm.AddStateTransition(TCPSocketLayer.States.Connecting, TCPSocketLayer.States.Connected, TCPSocketLayer.Transitions.ConnectionSuccess);

  this.fsm.AddStateTransition(TCPSocketLayer.States.Connecting, TCPSocketLayer.States.Disconnected, TCPSocketLayer.Transitions.ConnectionFailure);

  this.fsm.AddStateTransition(TCPSocketLayer.States.Connected, TCPSocketLayer.States.Disconnected, TCPSocketLayer.Transitions.Disconnect);

  this.fsm.SetCurrentState(TCPSocketLayer.States.Disconnected);

  }

  首先实例化一个有限状态机对象fsm,然后我们做了一个枚举值TCPSocketLayer,然后将其加入状态转换函数AddAllStates,比如AddStateTransition(TCPSocketLayer.States.Disconnected, TCPSocketLayer.States.Connecting, TCPSocketLayer.Transitions.StartConnect);

  表示是从Disconnected到Connecting之间的转换。

  函数的末尾是设置当前状态为Disconnected。

  如果我们关闭连接,我们可以使用Disconnect状态,如下函数所示:

  public void Kill()

  {

  this.fsm.ApplyTransition(TCPSocketLayer.Transitions.Disconnect);

  this.connection.Close();

  }

  总结一下:刚开始我们要把所有的状态之间的切换加入到表里,后面我们就可以随意的使用状态了。以上主要是利用网络通信举的事例。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表