引言:实现游戏 AI 的方式有很多,目前最为常用的主要有有限状态机和行为树。和有限状态机相比,行为树有更好的可扩展性和灵活性,能实现更复杂的 AI 需求。开发者honmono在 Cocos Creator 中用一个ECS + BehaviorTree 框架实现了一个格斗 AI Demo,一起来看看他的方案。
写一个 ECS 框架
ECS 全称 Entity - Component - System(实体-组件-系统)。组件只有属性没有行为,系统只有行为没有属性。
什么是 ECS 呢?网上已经有很多介绍 ECS 的文章了,这里不再赘述,直接贴几篇我个人觉得写的好的,谈一谈我的理解:
《浅谈中的 ECS 架构》
https://blog.codingnow.com/2017/06/overwatch_ecs.html
这篇文章应该是最早一批介绍 ECS 架构的文章了,不仅全面地介绍了 ECS 架构,还对比了 ECS 和传统游戏开发架构的区别,以及在网络同步时的处理。
《游戏开发中的 ECS 架构概述》
https://zhuanlan.zhihu.com/p/30538626
这篇文章比较接地气,文中提到:
ECS 的模式遵循组合优于继承原则,游戏内的每一个基本单元都是一个实体,每个实体又由一个或多个组件构成,每个组件仅仅包含代表其特性的数据(即在组件中没有任何方法),例如:移动相关的组件 MoveComponent 包含速度、位置、朝向等属性,一旦一个实体拥有了 MoveComponent 组件便可以认为它拥有了移动的能力,系统便是来处理拥有一个或多个相同组件的实体集合的工具,其只拥有行为(即在系统中没有任何数据),在这个例子中,处理移动的系统仅仅关心拥有移动能力的实体,它会遍历所有拥有 MoveComponent 组件的实体,并根据相关的数据(速度、位置、朝向等),更新实体的位置。
实体与组件是一个一对多的关系,实体拥有怎样的能力,完全是取决于其拥有哪些组件,通过动态添加或删除组件,可以在(游戏)运行时改变实体的行为。
这段话对于 ECS 的关系也是我设计的框架遵守的规则,即 Component 只包含属性,System 只包含行为。
这个 ECS 框架做了什么
World-Entity-Component-System 的关系图
World 每帧根据顺序调用所有的 System,System 中会处理对应的 Component。在这个过程中,使用者可以动态创建或销毁 Entity,给 Entity 添加或移除 Component。
为了更高效地维护 Entity-Component-System 的关系,我采取了一些办法。
1、所有的 Component 都通过其对应的 ComponentPool 维护。
例如 MoveComponent 会生成一个 MoveComponentPool 进行维护,方便实现复用。 外面不直接持有 Component,而是通过 component 在 pool 中的 index 索引便可以在对应的 poo