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, 来达到同一状态,不一样表现行为的目的!
这种设定须要在状态转化以前完成。