ECS 简介

可参考的官方例子: ecs_guide.

还可以参考完整的游戏实例: alien_cake_addict, breakout.


ECS 作为数据结构

Bevy 使用 Bevy ECS(Entity-Component System)为你存储和管理所有数据。

从概念上讲,你可以把它与数据库或电子表格中的表格进行类比。你的不同数据类型(组件)就像表格的"列","行"(实体)包含多个组件的值或实例。

例如,你可以为你的游戏创建一个 Health 组件。然后,你可以有许多实体代表你游戏中的不同事物,如玩家、NPC 或怪物,所有这些事物都可以有一个 Health 值(以及其他相关组件)。

这使得编写游戏逻辑(Systems)变得很容易,它可以对任何具有必要组件的实体进行操控(例如健康/伤害系统可以操控任何具有 Health 的事物),不管那是玩家、NPC 还是怪物(或其他什么)。这使得你的游戏逻辑非常灵活和可重复使用。

一个给定的实体所具有的组件的集合或组合,被称为实体的原型。

请注意,实体并不局限于"游戏世界中的对象"。ECS 是一个通用的数据结构。你可以创建实体和组件来存储任何数据。

性能

Bevy 有一个智能的调度算法,可以尽可能地并行运行你的系统。当你的函数不需要对相同的数据进行冲突的访问时,它就会自动这样做。你的游戏将可以"自由"地扩展到在多个 CPU 核心上运行,也就是说,不需要你额外的开发努力。

为了尽可能地提高并行化运行,你可以使你的数据和代码更加细化。将你的数据分割成更小的类型和结构。将你的逻辑分成多个小的系统或函数。让每个系统只访问与它相关的数据。访问冲突越少,游戏的运行速度就越快。

Bevy 性能的一般经验法则是:越细化越好。

给来自面向对象语言程序员的提示

你可能已经习惯了用"对象类"来思考。例如,你可能会想定义一个大的单体结构 Player,包含玩家的所有字段和属性。

在 Bevy 中,这被认为是不好的做法,因为这样做会使你的数据更难处理,并限制性能。

相反,当不同的数据片断可以被独立访问时,你应该让数据变得更细化。

例如,将游戏中的玩家表现为一个实体,由独立的组件类型(独立的 struct)组成,如健康、XP 或任何与你的游戏有关的东西。你也可以将标准的 Bevy 组件如 TransformTransform 解释)附加到它上面。

这将使你更容易开发你的系统(游戏逻辑和行为),以及使你的游戏运行性能更好。

当然,像 Transform 这样的东西,或者一组坐标,不进一步细化,而作为一个单一的结构同样是有意义的,因为它的字段不可能独立发挥作用。