预制实例化成Entity
前言
从Authoring模式中,如何通过预制件来实例化一个对应的Entity对象到DOTS系统中。
一、Authoring模式与Runtime模式
Authoring创作模式:即我们熟悉的方便操作的创建预制的模式
Runtime模式:运行模式,即在运行时,在subScene中对应的Entity模式
点击右上角可以更改模式。
可以方便的查看对应Entity的相关信息:比如它由哪些Component组成,对应的Aspect,以及关联的System。
二、转换一个SubScene中的GameObject
1.自动转
在Scene中创建一个subScene。
将一个预制,或者GameObject放到这个subScene中,则Unity内置的脚本会被自动转换为对应的Component。注意有一些组件比如渲染相关的,需要运行起来才能看到对应的Component。
2.自定义组件的转换
部分自定义的组件,需要我们利用DOTS提供的接口,来转换成对应的Component附加到Entity中去。
如官网提供的实例:
public class MyAuthoring : MonoBehaviour
{
public int Value;
}
public struct MyComponent : IComponentData
{
public int Value;
public float3 Position;
}
public class MyBaker : Baker<MyAuthoring>
{
public override void Bake(MyAuthoring authoring)
{
// Accessing the transform using Baker function, not the GameObject one
// so the this baker can keep track of the dependency
var transform = GetComponent<Transform>();
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new MyComponent
{
Value = authoring.Value,
Position = transform.position
} );
}
}
利用Baker转换对应的Component到对应的Entity中。
具体步骤:
- 定义一个自己想要添加到Entity身上的Component结构
- 在想要挂载这个Component的Entity对应的GameObject身上挂载一个MonoBehaviour脚本,脚本的内容就是你想要转换为对应Component的内容。
- 声明一个继承于Backer的类,泛型参数为你想要转换的MonoBehaviour脚本类
- 在对应的Bake函数中,利用Baker类中的结构,GetEntity获取对应的Entity。
- new 一个你想要添加到这个Entity上的Component结构,然后通过AddComponent给获取到的Entity添加上对应的组件
- 给这个Component实例的变量进行赋值。
这样就实现了把一个MonoBehaviour脚本中的数据,转成Component添加到对应的Entity上了
3.预制体的转换
上面写的都是放到subScene来转换entity实例,下面说说如何将预制体转换为对应的Entity实例。
1.首先挂载一个GameObject到SubScene中,挂载一个MonoBehaviour脚本,MonoBehaviour脚本中定义一个Public的GameObject变量暴露给Inspect使用,然后通过将一个预制移动到Inspector的MonoBehaviour脚本上的对应GameObject变量上。这一点与以前实例化GameObject差不多。
2.写一个MonoBehaviour脚本对应的Baker类,然后通过GetEntity(GameObject, TransformUsageFlags)接口获取到挂载到MonoBehaviour身上对应的预制的Entity。
3.这个预制也会被转换成一个subScene中的Entity,所以也可以通过GetEntity获取到这个Entity。
以上就是常规的预制转换成Entity的流程,接下来要利用EntityManager.Instantiate接口来实例化更多相同的Entity。
4.将上面的预制Entity存到某个Component中用于实例化。
5.通过SystemAPI.GetSingleton获取上面单例Component,然后CollectionHelper.CreateNativeArray接口申请对应数量的Entity容器。
6.调用state.EntityManager.Instantiate,传入Component中缓存的Entity,以及申请好的NativeArray<Entity>容器变量,NativeArray<Entity>变量会填充好实例化后的所有Enitity。
7. 再针对这些Entity进行自己想要的操作,比如添加对应的Component,或者修改预制Prefab中通过Bake添加的Component的属性值等。
8. dispose掉临时的NativeArray<Entity>容器变量
总结
只要添加到SubScene中的预制都会经过Bake,转换成对应的Entity,包括用Public GameObject方式链接的,也包括嵌套链接的。最好是通过来查看非运行状态下Runtime模式中的Entity,就可以知道SubScene中有多少嵌套的预制被转换。
每个预制都可以通过bake这个流程进行任意转换自定义Component,同时也可以将对应的Entity缓存到Component中,然后通过.EntityManager.Instantiate来批量实例化Entity,这个有点像以前实例化预制的接口,不同的是需要提前申请对应的Entity的NativeArrary空间来存放实例化的Entity,最后可以通过填充好的NativeArrary的Entity数组来遍历进行一些额外操作。