通用组件

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()此外,出于序列化目的,托管组件必须是默认可构造的。

您必须在主线程上设置组件的值。为此,请使用 EntityManagerEntityCommandBuffer因为组件是引用类型,所以您可以更改组件的值,而无需跨块移动实体,这与ISharedComponentData不同这不会创建同步点。

然而,虽然托管组件在逻辑上与值类型组件分开存储,但它们仍然有助于实体的EntityArchetype定义。因此,向实体添加新的托管组件仍会导致 ECS 创建新的原型(如果匹配的原型不存在)并将实体移动到新的 Chunk。

有关示例,请参阅文件:/Packages/com.unity.entities/Unity.Entities/IComponentData.cs.

posted @ 2021-09-24 00:09  alps_01  阅读(93)  评论(0编辑  收藏  举报