Unity Enitity Component System 参考手册 - 2.3 Component
基于0.11.1-preview 4 版本
2.3 Components
component是ECS体系结构的三个主要元素之一。它们代表游戏或应用程序的数据。entity是为component集合建立索引的标识符,而系统则提供了行为。ECS中的component是具有以下 “标记接口”(marker interfaces) 之一的结构:
ECS中的component是具有以下“标记接口”之一的结构:
IComponentData
用于通用component和chunk component。IBufferElementData
将动态缓冲区与entity相关联。ISharedComponentData
按archetype中的值,对entity进行分类或分组。有关更多信息,请参见Shared Component Data。ISystemStateComponentData
将system特定的状态与entity相关联,并检测何时创建或销毁各个entity。有关更多信息,请参见System State Components。ISharedSystemStateComponentData
共享状态和system状态数据的组合。请参阅[System State Components。- `Blob assets 尽管从技术上讲Blob不是component,但您可以使用Blob asset来存储数据。Blob asset可以由一个或多个component,通过使用BlobAssetReference进行引用,并且是不可变的。您可以使用Blob asset在asset之间共享数据,并访问C# job中的数据。
EntityManager
将若干个component的组合,组织到archetype中。它将具有相同archetype的所有entity的component,一起存储在称为chunk的内存chunk中。给定chunk中的entity均具有相同的componentarchetype。
该图说明了ECS如何按archetype存储component数据chunk。共享component和chunk component是例外,因为ECS将它们存储在chunk的外部。这些component类型的单个实例适用于适用chunk中的所有entity。此外,可以选择将动态缓冲区存储在chunk之外。即使ECS不在chunk内存储这些类型的component,在查询entity时,通常也可以将它们与其他component类型视为一类。
2.3.1 General purpose components
ComponentData
在Unity中(在标准ECS术语中也称为组件),是一个仅包含entity的实例数据的结构。ComponentData
不应包含用来访问数据的方法。您应该在system中实现所有游戏逻辑和行为。这有点类似于UnityEngine.Component
类,但是只包含成员变量。不包含成员方法。
Unity ECS API提供了一个名为IComponentData
的接口,您可以在代码中实现该接口,以声明通用组件类型。
2.3.1.1 IComponentData
传统的Unity组件(包括MonoBehaviour)是面向对象的类,其中包含行为的数据和方法。IComponentData是纯ECS样式的组件,这意味着它没有定义任何行为,仅定义了数据。您应该实现IComponentData
为struct
而不是class
,这意味着默认情况下,它是通过值而不是通过引用复制的。通常,您需要使用以下模式来修改数据:
1var transform = group.transform[index]; // Read
2transform.heading = playerInput.move; // Modify
3transform.position += deltaTime * playerInput.move * settings.playerMoveSpeed;
4group.transform[index] = transform; // Write
继承自IComponentData
接口的结构不得包含对托管对象的引用。这是因为这种结构不被存放在托管堆中。
2.3.1.2 Managed IComponentData
使用托管IComponentData
(即,IComponentData
使用class
而不是进行声明struct
)有助于将现有代码以零碎的方式移植到ECS,与不适合的托管数据进行互操作ISharedComponentData
,或者为数据布局提供archetype。
这些组件的使用方式与值类型相同IComponentData
。但是,ECS在内部以完全不同(且较慢)的方式处理它们。如果不需要托管组件支持,需定义一个UNITY_DISABLE_MANAGED_COMPONENTS
宏,以防止误用上它。
因为托管IComponentData
是托管类型,所以与值类型的IComponentData
相比,它有以下的性能缺点:
- 不能与Burst编译器一起使用
- 不能在JOB结构中使用
- 它不能使用chuck内存
- 需要使用GC
您应该尝试限制托管组件的数量,并尽可能使用 blittable类型 (即值类型)。
继承实现托管IComponentData
接口必须实现IEquatable<T>
接口并重写Object.GetHashCode()
。此外,出于序列化的目的,这个继承实现的类必须是默认可构造的。必须在主线程上设置component的值。为此,请使用EntityManager或EntityCommandBuffer。由于这种托管component是引用类型,因此与ISharedComponentData
不同,可以更改component的值而无需在块之间移动entity。这不会创建一个同步点。
尽管在逻辑上将托管component与值类型的component分开存储,但它们仍然有助于entity的EntityArchetype定义。这样,向entity添加新的托管component,如果尚不存在匹配的archetype,仍会导致ECS创建新的archetype,并将entity移至新的Chunk。
有关示例,请参见文件:/Packages/com.unity.entities/Unity.Entities/IComponentData.cs。