有限状态机在过去十年里变得非常流行,游戏开发者用它开发了很多极具趣味的游戏。但再好的事情也有个结束,是否到了使用比 FSM 更好的技术来完成 AI 逻辑的时代了?
让我把它改得更有建设性一些:
“据我所知很多领域(如游戏业界)都使用有限状态机来实现游戏 AI。为什么你不用它来实现这个模拟游戏里的狗的行为?”
这个教程使用行为树来体现它与状态机的不同,而且游戏 AI 开发者也能够从中得到分级逻辑的好处。
当然我们也可以用有限状态机(FSM)来构建相同的行为。但业内人士都知道这一技术在逻辑增长时有多么有脆弱。远离 FSM 是避免游戏项目变得一塌糊涂的选择!
非正统
问题: 构建 FSM 的方式对于不同的软件工程师而言是完全不同的流程。是的,概念上它是“设计师友好”的,但实际上应用 FSM 需要应用非常多的编程知识和细节。
原因: FSM 要求每一个状态明确地转换到另一状态。没有一个编程语言需要这样,语言本身的语义就隐含了所有转换(如C++编译器从语句构造执行指令序列)。
过于底层
问题: 编辑FSM的逻辑非常底层,而且机械性十足。我们常常会发现自己总是在构建相似的行为,而且这会花费我们大部分时间。
原因: 我们所能做的仅是编辑从一状态到另一状态的转换,而无法做出更高层次的模式导致频繁重复相似的序列或条件。有限状态机的世界不存在元编程(Meta-programming)。
逻辑受限
问题: 有限状态机形式固定,从而导致计算受限(又称为非图灵完备)。这意味着我们不能像计数一样做事。
原因: 如果我们把事件当作符号,我们只能用有限状态自动机识别正则文法,这一方法下一个正则表达式不能识别某些类别的文本模式。同样,有限状态机仅能作为正则语言的传感器。
需要自定义扩展
问题: 游戏开发者在实践中经常需要扩展 FSM 才能将其用于项目,然而这并不容易被理解,甚至还缺乏文档。这是与FSM的学术基础并不相同。
原因: 因为 FSM 受限于理论,开发者必须自行增加功能扩展以实现确定的某些特性。这意味着要用编程语言去实现计数器、计时器和任何形式的内存对象。
难以标准化
问题: 不像规划器(HTN)或搜索算法(A*),它们能用相关的通用方法实现。而 FSM 则非常难以在不同的游戏间重用,甚至在引擎是不同的部分重用也不可能。
原因: 因为 FSM 是非图灵完备的, FSM 需要为每一问题自定义特定的解决方案。这使得它们适用度极低,而不像脚本语言一样能够很容易地重新打包。
非自主的
问题: 使用 FSM 实现目标导向的行为需要做很多工作。这是一个大问题,因为大部分有针对性的 AI 需要处理长远目标。
原因: FSM 运作于反应模式,只能处理事件和触发跳转。它们无法自动向前(又称为自主),因此我们必须为所有不同的目标手动转换。
难以并发
问题: FSM 难以并发。当并行运行多个状态机,要么死锁,要么我们通过手工编辑来确保它们在某个程度上能够兼容。
原因: FSM 存储的信息越多在处理外部资源冲突上的问题就越多。使状态机并发的解决方案通常是扩展 FSM 自身,把它作为支持逻辑或一套工具来保证并发安全。
大规模支持较差
问题: 有限状态机,甚至是分层的,也难以大规模扩展。它们往往是在其中夹杂一大块逻辑代码,而非行为编辑模块化。
原因: FSM 并不利用编程语言提供的用以解决大问题的规模化特性,同样地FSM 也难以同步多个行为模块。
劳动密集型
问题: 用 FSM 实现任何设计都需要做大量工作。甚至状态机本身也有着无数问题。
原因: 如前所述,应对所有挑战需要花费设计师的大量时间,甚至最终这还会成行为中的 bugs 的来源!
行业进步
事实: 许多资深游戏开发者已经不再使用有限状态机,而是使用行为树之类的可替换方案。
事实: 现在多个游戏 AI 中间件提供商致力于规划器实现的 AI,在 2008 年将会见到更多可用的此类产品。
结论
FSM,就像其它技术一样,在游戏开发的进程中占有了应得的一席之地。然而,开发者默认使用有限状态机来实现 AI 的时代,已经行将结束。带有协程的脚本在今天已经极其流行,而分级规划器将越来越多地应用在游戏及其中间件