实体组件系统
什么是实体组件系统?(What is Entity Component System?)
Entity Component System is a software pattern commonly employed in game development.
实体组件系统是游戏开发中常用的一种软件模式。
It is designed to take full advantage of a computer’s hardware to maximize performance, whilst also providing the programmer with a structured, modular environment.
它旨在充分利用计算机硬件的优势来最大化性能,同时还为程序员提供结构化的模块化环境。
The pattern comprises three parts: entities, components, and systems.
该模式包括三个部分:实体,组件和系统。
一个例子 (An Example)
To better explain the concepts involved in the ECS pattern, consider a 2D platformer with the following objects:
为了更好地解释ECS模式中涉及的概念,请考虑具有以下对象的2D平台程序:
- A player controlled by a mouse and keyboard. 由鼠标和键盘控制的播放器。
- A static tree. 一棵静态树。
- Two zombies controlled by AI. 由AI控制的两个僵尸。
在OOP中会是什么样? (What Would this Look Like in OOP?)
In object oriented programming, data and functionality are kept tightly encapsulated within classes, promoting inheritance like in the following diagram:
在面向对象的编程中,数据和功能紧密地封装在类中,从而促进了继承,如下图所示:
Here, a parent GameObject class contains all common data and functionality. Different classes would inherit and override this.
在此,父GameObject类包含所有通用数据和功能。 不同的类将继承并覆盖它。
ECS中的情况如何? (What Would this Look Like in ECS?)
ECS doesn’t keep data and functionality coupled together in classes, nor does it use inheritance. Instead, it seperates them like in the diagram below:
ECS不会将数据和功能保持在类中耦合在一起,也不会使用继承。 相反,它将它们分开,如下图所示:
All data is seperated into small, specialised components, and all functionality and logic is kept in specialised systems. The entity is an identifier that binds everything together.
所有数据都分离为小型的专用组件,所有功能和逻辑均保存在专用系统中。 实体是将所有内容绑定在一起的标识符。
Following is a more detailed description of the three concepts of ECS.
以下是对ECS的三个概念的更详细描述。
实体 (Entity)
An entity is an individual object in the world. The following diagram shows the four entities in our game:
实体是世界上的单个对象。 下图显示了我们游戏中的四个实体:
In a program using ECS, each entity is represented by a unique integer id. The entity itself contains no data or functionality; it is just an integer.
在使用ECS的程序中,每个实体都由唯一的整数ID表示。 实体本身不包含任何数据或功能; 它只是一个整数。
组件 (Components)
All the data associated with an entity is seperated into small, generic, and reusable components.
与实体相关联的所有数据都被分离为小型,通用且可重用的组件。
Below are eight example components:
以下是八个示例组件:
Each component is specific, independent, and usually contains only primitive data types like integers or floats.
每个组件都是特定的,独立的,并且通常仅包含原始数据类型,例如整数或浮点数。
For example, the following code represents the Position component:
例如,以下代码表示位置组件:
1. public struct Position
2. {
3. public float x;
4. public float y;
5. }
Components are lightweight data containers that define the attributes and state of an entity. They contain no functionality, just data.
组件是轻量级的数据容器,用于定义实体的属性和状态。 它们不包含任何功能,仅包含数据。
The following diagram shows the four entities in our game alongside the components attached to them.
下图显示了我们游戏中的四个实体以及与其相连的组件。
All four entities have a Position and Render component. Entity 0, 1, and 2 have a Physics component, but entity 3 does not. Entity 0 has a PlayeInput component and entity 1 and 2 have an AI component.
所有四个实体都具有“位置和渲染”组件。 实体0、1和2具有Physics组件,但实体3没有。 实体0具有PlayeInput组件,而实体1和2具有AI组件。
Components on there own just store data. They do not contain any methods and do not have any functionality. How the variables in a component are interpreted is not the concern of the component.
那里的组件仅存储数据。 它们不包含任何方法,也不具有任何功能。 组件中不关心如何解释组件中的变量。
组件阵列 (Component Array)
As mentioned, entities are just integers that don’t need to be stored anywhere. Components, however, do need to be stored in memory and are usually stored in arrays like in the following diagram:
如前所述,实体只是整数,不需要存储在任何地方。 但是,组件确实需要存储在内存中,并且通常存储在数组中,如下图所示:
Each component type will have its own one dimensional array with each instance of a component being stored contiguous to the next.
每种组件类型都有自己的一维数组,每个组件实例与下一个实例相邻存储。
The relationship between the entity id and the component array depends heavily on how the ECS is implemented. Often, the entity id maps either directly or indirectly to the index of the array that the entity’s component is located.
实体ID与组件数组之间的关系在很大程度上取决于ECS的实现方式。 通常,实体ID直接或间接映射到实体组件所在的数组的索引。
For example the Position component attached to entity 35 will be at index 35 in the Position components array.
例如,附加到实体35的Position组件将位于Position组件数组中的索引35处。
系统篇 (Systems)
Systems bring the game to life. They operate on the components attached to an entity to produce changes in the world.
系统使游戏栩栩如生。 它们在与实体相连的组件上进行操作以产生世界变化。
The following diagram shows four example systems:
下图显示了四个示例系统:
Each system is updated once per frame. During this, a set of entities, which are selected according to some filter, are iterated, and their attached components are modified.
每个系统每帧更新一次。 在此期间,将迭代根据某些过滤器选择的一组实体,并修改其附加组件。
Take the GravitySystem for example. Its requirements are that an entity has an attached Position and Physics component. The following code demonstrates what the update loop could look like:
以重力系统为例。 它的要求是实体具有附加的“位置和物理”组件。 以下代码演示了更新循环的外观:
1. foreach (int e in GetEntities<Position, Physics>())
2. {
3. Physics phy = physics[e];
4. Position pos = position[e];
5.
6. phy.velocity_y -= 9.81f;
7. pos.y += phy.velocity_y;
8. }
(This code is for demonstration purposes and will not compile)
(此代码仅用于演示目的,不会编译)
Line 1 iterates over every entity that has the required Position and Physics components.
第1行遍历具有所需“位置和物理”组件的每个实体。
- Line 3 and 4 grabs the instances of each component belonging to the current entity from the relevant component arrays. 第3和第4行从相关组件数组中获取属于当前实体的每个组件的实例。
- Line 6 and 7 modify the component instances. 第6和7行修改了组件实例。
The GravitySystem will only work on entities that have the required components, which in our game, is entity 0, 1, and 2. Entity 3 does not have an attached Physics component and so is not used by the GravitySystem.
GravitySystem将仅在具有必需组件的实体上工作,在我们的游戏中,实体是实体0、1和2。实体3没有附加的Physics组件,因此GravitySystem不会使用它。
Like components, systems are specific. The GravitySystem applies gravity. A RenderSystem renders entities with a Position and Render component. A HealthRegenSystem regenerates the health of entities with a Health component.
像组件一样,系统也是特定的。 GravitySystem应用重力。 RenderSystem使用“位置和渲染”组件渲染实体。 HealthRegenSystem使用“健康”组件重新生成实体的健康。
结论 (Conclusion)
Hopefully, this article has successfully introduced the basic concepts of ECS.
希望本文成功介绍了ECS的基本概念。
Actually implementing an ECS can be a challenge. Fortunately, there are lots of resources online that can help with this. Below are some that I used.
实际实施ECS可能是一个挑战。 幸运的是,在线上有很多资源可以帮助您解决此问题。 以下是我使用过的一些内容。
翻译自: https://medium.com/@dean.j.k.james/introduction-to-entity-component-system-64c371f274bd
实体组件系统