最新开源方案!Cocos Creator 写一个ECS框架+行为树,实现格斗游戏 AI

引言:实现游戏 AI 的方式有很多,目前最为常用的主要有有限状态机和行为树。和有限状态机相比,行为树有更好的可扩展性和灵活性,能实现更复杂的 AI 需求。开发者 honmono 在 Cocos Creator 中用一个 ECS + BehaviorTree 框架实现了一个格斗 AI Demo,一起来看看他的方案。

99f854025293248d5a49ca3c8fba6826.gif

Demo 示例

这个格斗 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 框架做了什么

35ab8096c7b30dae3d81502f4f7e0b3d.png

World-Entity-Component-System 的关系图

World 每帧根据顺序调用所有的 System,System 中会处理对应的 Component。在这个过程中,使用者可以动态创建或销毁 Entity,给 Entity 添加或移除 Component。

为了更高效地维护 Entity-Component-System 的关系,我采取了一些办法。

1、所有的 Component 都通过其对应的 ComponentPool 维护。

例如 MoveComponent 会生成一个 MoveComponentPool 进行维护,方便实现复用。 外面不直接持有 Component,而是通过 component 在 pool 中的 index 索引便可以在对应的 pool 中获取到对应的 Component。

2、Entity 使用自增 Idx 标识。当有 entity 被销毁时,会回收 idx。

外部不需要持有 Entity 对象,或者说没有 Entity 对象,所有的 Entity 都是一个 Idx, 通过这个 Idx 在 world 内进行操作。

3、System 通过 Filter 类管理关注的 Entity。

上文中提到 System 为了处理其关心的 ComponentA,会遍历所有拥有该 ComponentA 的 Entity。但是怎么判断哪下 Entity 有这个 ComponentA 呢? 传统的方法会遍历所有的 Entity,判断其是否有 ComponentA,这种方案明显是不够高效的。 所以这里引入了 Filter 类, 其方法的核心是空间换时间并有一套判断规则(接收某些类型的组件, 拒接某些类型的组件), 当每次进行 AddComponent 和 RemoveComponent 或者 RemoveEntity 等会影响实体的操作时,会通知所有的 Filter 有实体进行了修改,Filter 会判断该实体是否还符合条件(也就是判断是否有 ComponentA),选择是否在 Filter 中保留该实体。那么当 System 需要遍历某些特定的 Entity 时,就可以直接通过对应的 Filter 就可以获得了。

4、Entity 和 Component 的关系可以用一张二维表维护。

eb50c7e6a54945536a1a796cbe806dbe.png

如上述表格中 Compone

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值