在Hierarchy中创建GameObject实例,由插件中的ConvertToEntity
在运行时把实例转换成Entity实例,RotationSpeedAuthoring_ForEach
负责具体转换工作(添加组件数据等…)
RotationSpeedAuthoring_ForEach
:把设置的参数DegreesPerSecond
(角度速率)转成ComponentData(弧度速率)并绑定到entity上。
RotationSpeed_ForEach
:这是个ComponentData,Entity实例的数据,注意它是结构体(Struct)不是类(Class)。
RotationSpeedSystem_ForEach
:组件系统,负责把ComponentData应用到Entity上,它在OnUpdate中对所有的Entity进行设置,Entities.ForEach会经常用到。
This sample demonstrates a simple ECS System that rotates a pair of cubes.
## What does it show?
This sample demonstrates the separation of data and functionality in ECS. Data is stored in components, while functionality is written into systems.
The **RotationSpeedSystem_ForEach** *updates* the object's rotation using the *data* stored in the **RotationSpeed_ForEach** Component.
## ComponentSystems and Entities.ForEach
RotationSpeedSystem_ForEach is a ComponentSystem and uses an Entities.ForEach delegate to iterate through the Entities. This example only creates a single Entity, but if you added more Entities to the scene, the RotationSpeedSystem_ForEach updates them all — as long as they have a RotationSpeed_ForEach Component (and the Rotation Component added when converting the GameObject's Transform to ECS Components).
Note that ComponentSystems using Entities.ForEach run on the main thread. To take advantage of multiple cores, you can use a JobComponentSystem (as shown in the next HelloCube example).
## Converting from GameObject to Entity
The **ConvertToEntity** MonoBehaviour converts a GameObject and its children into Entities and ECS Components upon Awake. Currently the set of built-in Unity MonoBehaviours that ConvertToEntity can convert includes the Transform and MeshRenderer. You can use the **Entity Debugger** (menu: **Window** > **Analysis** > **Entity Debugger**) to inspect the ECS Entities and Components created by the conversion.
You can implement the IConvertGameObjectEntity interface on your own MonoBehaviours to supply a conversion function that ConvertToEntity will use to convert the data stored in the MonoBehaviour to an ECS Component.
In this example, the **RotationSpeedAuthoring_ForEach** MonoBehaviour uses IConvertGameObjectEntity to add the RotationSpeed_ForEach Component to the Entity on conversion.
在MonoBehaviour中可以生成一堆的Entity实例,并对它们初始化
HelloSpawnMonoBehaviour
:把GameObject预制体转成EntityPrefab,再由World.Active.EntityManager
实例化。初始化的时候给实例添加自定义的:ComponentData(MoveUp
&MovingCube
),它们两个不存数据只做Tag用。
MovementSystem
:分两个部分,第一部分:在OnUpdate
中筛选出带有MoveUp
&MovingCube
组件的Entity实例,对它们进行位置偏移操作,当到达条件时删除(PostUpdateCommands.RemoveComponent
)掉MoveUp
组件取消对它的偏移操作,第二部分:筛选出不带MoveUp
的所有带MovingCube
组件的Entity实例重置它的位置并重新添加(PostUpdateCommands.AddComponent
)MoveUp
组件。这两个部分就起到了循环Entity实例位置运动的功能。
This sample demonstrates a simple ECS System that uses fluent queries to select the correct set of entities to update.
The example defines two tag component, named MovingCube and MoveUp. One fluent query in the system selects all entities that have both a MoveUp component and a Translation component. The ForEach lambda function associated with this query moves each selected entity upwards until it reaches a certain height. At that point, the function removes the MoveUp component so the next time the system updates, the entity will not be selected and thus it will not be moved upwards any farther.
A second fluid query selects all entities that have a Translation component, but do not have a MoveUp component. The ForEach function associated with the second query moves the entity down to its starting location and adds a new MoveUp component. Since the entity has a MoveUp component once again, the next time the system updates, the entity is moved upward by the first ForEach function and skipped by the second query.
The MovingCube is another tag component that ensures that the system only works on components marked for this sample.
## What does it show?
This sample demonstrates a simple ECS System that uses fluent queries to select a set of entities to move upwards. When they reach a certain height, the system removes a component and uses another query to respawn them at a lower height. It also demonstrates the use of "tag" components to provide a means of selecting specific sets of entites with marker components to be processed.
## Component Systems and Entities.ForEach
MovementSystem is a ComponentSystem and uses an Entities.ForEach delegate to iterate through the Entities. This example uses the WithAll and WithNone constraints to select specific sets of entities to work on.
Note: Component Systems using Entities.ForEach run on the main thread. To take advantage of multiple cores, you can use a JobComponentSystem (as shown in other HelloCube examples).
由于Component System
使用的Entities.ForEach
是运行在主线程中的,如果需要多核方式就可以使用JobComponentSystem
。
只需要修改System部分即可。如下:
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
// This system updates all entities in the scene with both a RotationSpeed_IJobForEach and Rotation component.
// ReSharper disable once InconsistentNaming
public class RotationSpeedSystem_IJobForEach : JobComponentSystem
{
// Use the [BurstCompile] attribute to compile a job with Burst. You may see significant speed ups, so try it!
[BurstCompile]
struct RotationSpeedJob : IJobForEach<Rotation, RotationSpeed_IJobForEach>
{
public float DeltaTime;
// The [ReadOnly] attribute tells the job scheduler that this job will not write to rotSpeedIJobForEach
public void Execute(ref Rotation rotation, [ReadOnly] ref RotationSpeed_IJobForEach rotSpeedIJobForEach)
{
// Rotate something about its up vector at the speed given by RotationSpeed_IJobForEach.
rotation.Value = math.mul(math.normalize(rotation.Value), quaternion.AxisAngle(math.up(), rotSpeedIJobForEach.RadiansPerSecond * DeltaTime));
}
}
// OnUpdate runs on the main thread.
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var job = new RotationSpeedJob
{
DeltaTime = Time.deltaTime
};
return job.Schedule(this, inputDependencies);
}
}
IJobChunk与IJobForEach类似,但是:Systems using IJobChunk can handle more complex situations than those supported by IJobForEach, while maintaining maximum efficiency.即IJobChunk更好点。
如果场景中有大量的物体,可以把它们分成一系列的SubScene,然后放到主场景中。
如下图所示SubScene是当前的主场景,Game View中的物体其实是RotatingCube子场景中的物体,通过SubScene
脚本实现。
如何在Monobehaviour中生成一个Entity实例呢?
首先通过GameObjectConversionUtility.ConvertGameObjectHierarchy(Prefab, World.Active);
把一般普通的预制体转成EntityPrefab,然后用
World.Active.EntityManager.Instantiate(prefab)
进行实例化。
未完待续