Creating gameplay
本节包含了关于如何在Unity编辑器中创建基于DOTS的游戏和其他应用程序的信息。它还包括ECS提供的系统和组件,以帮助你实现游戏功能。
这些系统包括:
- Unity.Transforms: 提供了定义世界空间变换的组件、三维物体层次结构和管理它们的系统。
- Unity.Hybrid.Renderer: 提供组件和系统以在Unity运行时渲染ECS实体。
Gameplay supporting packages
DOTS中的一些游戏功能需要额外的软件包来支持它们。关于需要额外软件包的功能列表,请看下面的表格。
Authoring overview
你可以使用Unity编辑器(使用必要的DOTS包)来创建基于DOTS的游戏。在编辑器中,你像平常一样使用GameObjects来创建一个场景,ECS代码将GameObjects转换为实体。
当你使用DOTS时,最大的区别是,你不需要编写自己的MonoBehaviours来存储实例数据和实现自定义游戏逻辑,而是定义ECS组件来在运行时存储数据,并为自定义逻辑编写系统。
GameObject conversion(游戏对象转化)
在GameObject转换过程中,各种转换系统处理它们所识别的MonoBehaviour组件,然后将其转换为基于ECS的组件。例如,Unity.Transforms转换系统之一会检查UnityEngine.Transform组件,并添加ECS组件,如LocalToWorld,以取代它。
你可以实现一个IConvertGameObjectToEntity MonoBehaviour组件来指定自定义转换步骤。ECS转换的GameObjects的数量和它创建的实体的数量之间往往不是一对一的关系;GameObject上的MonoBehaviour的数量和它添加到实体上的ECS组件的数量之间也不是一对一的。
如果一个GameObject有ConvertToEntity MonoBehaviour组件,或者它是SubScene的一部分,ECS转换代码就会转换它。在这两种情况下,为各种DOTS特性提供的转换系统,如Unity.Transforms和Unity.Hybrid.Render,都会处理GameObject或Scene Asset以及它们的任何子GameObject。
用ConvertToEntity转换GameObjects和用SubScene转换GameObjects的一个区别是,ECS将转换SubScene所产生的实体数据序列化并保存到磁盘。你可以在运行时非常快速地加载或流化这些序列化的数据。相比之下,ECS总是在运行时用ConvertToEntity MonoBehaviours转换GameObjects。
最好的做法是使用标准的MonoBehaviours进行创作,并使用IConvertGameObjectToEntity将这些创作组件的值应用于IComponentData结构,以供运行时使用。通常情况下,用于编写的最方便的数据布局在运行时并不是最有效的数据布局。
你可以使用IConvertGameObjectToEntity来定制SubScene中的任何GameObject的转换,或具有ConvertToEntity单行为的GameObject,或具有ConvertToEntity单行为的GameObject的子对象。
NOTE
基于DOTS的应用程序的编写工作流程是一个积极开发的领域。大致的轮廓已经到位,但你应该预料到在不久的将来这个领域会有许多变化。
Generated authoring components(生成的编写组件)
Unity可以为简单的运行时ECS组件自动生成编写组件。当Unity生成一个编写组件时,你可以在编辑器中直接将包含ECS组件的脚本添加到一个游戏对象中。然后你可以使用检查器窗口来设置该组件的初始值。
对于IComponentData
Unity可以为简单的IComponentData组件自动生成编写组件。当Unity生成一个编写组件时,你可以在Unity编辑器中把一个IComponentData直接添加到场景中的一个游戏对象上。然后你可以使用检查器窗口来设置该组件的初始值。
为了表明你想生成一个编写组件,在IComponentData声明中添加[GenerateAuthoringComponent]属性。Unity会自动生成一个MonoBehaviour类,其中包含组件的公共字段,并提供一个转换方法,将这些字段转换为运行时组件数据。
[GenerateAuthoringComponent]
public struct RotationSpeed_ForEach : IComponentData
{
public float RadiansPerSecond;
}
注意以下限制:
- 在一个C#文件中,只有一个组件可以有一个生成的编写组件,而且该C#文件中不能有另一个MonoBehaviour。
- ECS只反映公共字段,而且它们的名称与组件中指定的名称相同。
- ECS将IComponentData中实体类型的字段反映为它所生成的MonoBehaviour中游戏对象类型的字段。ECS将你分配给这些字段的GameObjects或Prefabs转换为引用的Prefabs。
- 只有公共字段会被反射出来,而且它们的名字与组件中指定的名字相同。
- IComponentData中实体类型的字段在生成的MonoBehaviour中被反射为GameObject类型的字段。你分配给这些字段的GameObjects或Prefabs被转换为被引用的Prefabs。
对于IBufferElementData
你也可以通过添加[GenerateAuthoringComponent]属性为实现IBufferElementData的类型生成编写组件:
[GenerateAuthoringComponent]
public struct IntBufferElement: IBufferElementData
{
public int Value;
}
在这个例子中,一个名为IntBufferElementAuthoring的类(继承自MonoBehaviour)被生成,暴露了一个List类型的公共字段。在转换过程中,这个列表将被转换为DynamicBuffer,然后添加到转换后的实体中。
注意以下限制:
- 在一个C#文件中,只有一个组件可以有一个生成的编写组件,而且该C#文件中不能有另一个MonoBehaviour。
- 对于包含2个或更多字段的类型,不能自动生成IBufferElementData编写组件。
- 对于有明确布局的类型,IBufferElementData编写组件不能自动生成。