游戏中有限状态机实现

https://github.com/pzUH/HierarchicalStateMachine

http://unitygems.com/fsm2/

一:

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

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

switch ()

case A:

  xxx

通常switch块放到 对象的update方法中,每帧更新状态。

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

二:

具体的改善的做法:

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

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

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

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

例如一个简单的状态机:

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

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

增加空闲状态

增加选择状态

增加移动状态

初始化所有状态的转化关系

设定当前状态是空闲状态

三:

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

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

这个转化是由状态内部自己检测来产生的,因此需要外部一直保持刺激信号,直到内部修改状态为止,这种行为是电平触发。

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

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

 四:

可能存在这样一种情况:

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

 

五:层次状态机

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

例如法师的攻击状态:

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

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

因此每个状态需要增加:

当前状态所在层次

孩子属性所有的子状态

初始状态

 

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

进入一个状态 如果有初始状态则进入初始状态, 递归初始化状态。

退出一个状态,通常是转化到另外一个状态,则需要退出到下一个状态的相应的层级。

 

六: 状态机可配置action

一个状态下的行为可能因为当前上下文不同,而有不同。

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

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

因此给状态添加action 属性:

action 包含 enter exit update 函数

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

这种设定需要在状态转化之前完成。

 

 

 

posted @ 2013-04-02 19:25  liyonghelpme  阅读(325)  评论(0编辑  收藏  举报