通用组件
ECS 组件(不是托管UnityEngine.Component
类的实例)是一个结构体,它只包含实体的实例数据。ECS 组件不应包含实用程序以外的方法来访问结构中的数据。您应该在系统中实现所有游戏逻辑和行为。就面向对象的 Unity 系统而言,这类似于 Component 类,但只包含变量。
Unity ECS API 提供了一个名为IComponentData 的接口,您可以在代码中实现该接口以声明通用组件类型。
组件数据
传统的 Unity 组件(包括MonoBehaviour
)是面向对象的类,包含数据和行为方法。IComponentData
是一个纯 ECS 风格的组件,这意味着它不定义行为,只定义数据。您应该实现IComponentData
为结构而不是类,这意味着默认情况下它是按值复制而不是按引用复制。您通常需要使用以下模式来修改数据:
var transform = group.transform[index]; // Read
transform.heading = playerInput.move; // Modify
transform.position += deltaTime * playerInput.move * settings.playerMoveSpeed;
group.transform[index] = transform; // Write
IComponentData
结构不能包含对托管对象的引用。这是因为ComponentData
生活在简单的非垃圾收集的跟踪块内存中,它具有许多性能优势。
托管 IComponentData
使用托管IComponentData
(即,IComponentData
使用class
而非声明struct
)有助于以零碎的方式将现有代码移植到 ECS,与不适合在 中的托管数据互操作ISharedComponentData
,或构建数据布局原型。
这些组件的使用方式与值类型相同IComponentData
。但是,ECS 以一种非常不同(且速度较慢)的方式在内部处理它们。如果您不需要托管组件支持,请UNITY_DISABLE_MANAGED_COMPONENTS
在应用程序的播放器设置(菜单:编辑 > 项目设置 > 播放器 > 脚本定义符号)中定义以防止意外使用。
由于 managedIComponentData
是一种托管类型,因此与 value-type 相比,它具有以下性能缺陷IComponentData
:
- 它不能与突发编译器一起使用
- 它不能在作业结构中使用
- 它不能使用块内存
- 它需要垃圾收集
您应该尝试限制托管组件的数量,并尽可能使用 blittable 类型。
ManagedIComponentData
必须实现IEquatable<T>
接口并覆盖Object.GetHashCode()
. 此外,出于序列化目的,托管组件必须是默认可构造的。
您必须在主线程上设置组件的值。为此,请使用 EntityManager
或EntityCommandBuffer
。因为组件是引用类型,所以您可以更改组件的值,而无需跨块移动实体,这与ISharedComponentData不同。这不会创建同步点。
然而,虽然托管组件在逻辑上与值类型组件分开存储,但它们仍然有助于实体的EntityArchetype
定义。因此,向实体添加新的托管组件仍会导致 ECS 创建新的原型(如果匹配的原型不存在)并将实体移动到新的 Chunk。
有关示例,请参阅文件:/Packages/com.unity.entities/Unity.Entities/IComponentData.cs
.