游戏中有限状态机实现

https://github.com/pzUH/HierarchicalStateMachine git

http://unitygems.com/fsm2/ github

一: 函数

有限状态机用于管理游戏中对象的行为很是方便。 spa

最简单的有限状态机实现方式 对象

switch () 递归

case A: 游戏

  xxx 事件

一般switch块放到 对象的update方法中,每帧更新状态。 get

这种结构最大的问题是状态没有获得封装,而有限状态机中状态和状态之间是存在转化的,而转化的过程当中,须要清理上个状态的数据,准备下个状态的数据,这样就会形成大量的冗余代码,以及对当前状态的混乱。 it

二:

具体的改善的作法:

抽象出分离状态机 , 状态, 以及转化三个概念。

 状态机 包含一个当前状态, 全部状态, 包含update函数, 设置状态函数。

每一个状态都有一个名字,以及enter exit update 函数, 以及初始化转化关系的函数。

一个转化是属于某个状态的,在特定条件下,将当前状态转化到下一个状态。

例如一个简单的状态机:

空闲状态 <----->选择状态-------->移动状态------>空闲状态

初始化状态机的过程就是:

增长空闲状态

增长选择状态

增长移动状态

初始化全部状态的转化关系

设定当前状态是空闲状态

三:

这时候如何触发状态转化呢?

在每一个状态的update的过程当中,都会检测有没有转化条件知足,若是有则退出当前状态,进入下一个状态。

这个转化是由状态内部本身检测来产生的,所以须要外部一直保持刺激信号,直到内部修改状态为止,这种行为是电平触发。

还有一种触发方式是边沿触发,即外部每变化一次,就触发一次状态变化。

电平触发存在的问题就是可能会丢失事件。

 四:

可能存在这样一种状况:

一个事件发生致使A对象的状态变化,B对象的状态变化,这两个变化可能会都修改相同的对象的属性,这时候,应该确保逻辑上的前后顺序,或者保证只修改属于本对象的那些对象的属性。

 

五:层次状态机

对于一个复杂的对象可能有大量的状态,一种简化状态数量的方法就是创建装他的层次:

例如法师的攻击状态:

法师是连锁闪电攻击,攻击完初始目标以后,会寻找下一个目标, 找到则攻击,否者退出攻击状态;

而这三个子状态都是属于攻击状态这个大状态的。

所以每一个状态须要增长:

当前状态所在层次

孩子属性全部的子状态

初始状态

 

这样状态的进入,退出 和 转化时,就要相应的考虑子状态的问题:

进入一个状态 若是有初始状态则进入初始状态, 递归初始化状态。

退出一个状态,一般是转化到另一个状态,则须要退出到下一个状态的相应的层级。

 

六: 状态机可配置action

一个状态下的行为可能由于当前上下文不一样,而有不一样。

例如一个对象受到攻击以后, 根据攻击对象不一样,可能产生不一样的效果,例如若是攻击方是骑士,那么可能会被击退一格,攻击方是忍者,可能就会交换彼此的位置。

一样一我的攻击另一个对象,根据被攻击者不一样也会产生不一样的效果,例如若是是我方,那么交换位置,若是是敌方则产生伤害。

所以给状态添加action 属性:

action 包含 enter exit update 函数

 经过设定目标对象某个状态下的action, 来达到同一状态,不一样表现行为的目的!

这种设定须要在状态转化以前完成。

相关文章
相关标签/搜索