需要注意,ConversionMode分为ConvertAndDestory和ConverAndInjectGameObject,前者会将其本身与子物体转为Entity后会销毁GameObject,后者只有本身转为Entity后,且会在Hiearchy中额外生成该GameObject
public class RotationSpeedAuthoring_IJobEntityBatch : MonoBehaviour, IConvertGameObjectToEntity
{
public float DegreesPerSecond = 360.0F;
// The MonoBehaviour data is converted to ComponentData on the entity.
// We are specifically transforming from a good editor representation of the data (Represented in degrees)
// To a good runtime representation (Represented in radians)
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
var data = new RotationSpeed_IJobEntityBatch { RadiansPerSecond = math.radians(DegreesPerSecond) };
dstManager.AddComponentData(entity, data);
}
}
转换完成后,执行Convert(),可以在此处添加Component.
2. Monobehaviour中,通过PrefabAsset转化的Entity生成与Prefab的生成逻辑类似。
public class Spawner_FromMonoBehaviour : MonoBehaviour
{
public GameObject Prefab;
public int CountX = 100;
public int CountY = 100;
void Start()
{
// Create entity prefab from the game object hierarchy once
var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);
var prefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(Prefab, settings);
var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
for (var x = 0; x < CountX; x++)
{
for (var y = 0; y < CountY; y++)
{
// Efficiently instantiate a bunch of entities from the already converted entity prefab
var instance = entityManager.Instantiate(prefab);
// Place the instantiated entity in a grid with some noise
var position = transform.TransformPoint(new float3(x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F));
entityManager.SetComponentData(instance, new Translation {Value = position});
}
}
}
}
3. ComponentSystem中,通过PrefabAsset转化的Entity生成
一旦该Spawner转化为Entity,生成的数据便可获取。
//数据类
public struct Spawner_FromEntity : IComponentData
{
public int CountX;
public int CountY;
public Entity Prefab;
}
//Mono挂载,并不直接生成,而是将数据存在该Entity上
public class SpawnerAuthoring_FromEntity : MonoBehaviour, IDeclareReferencedPrefabs, IConvertGameObjectToEntity
{
public GameObject Prefab;
public int CountX;
public int CountY;
// Referenced prefabs have to be declared so that the conversion system knows about them ahead of time
public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
{
referencedPrefabs.Add(Prefab);
}
// Lets you convert the editor data representation to the entity optimal runtime representation
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
var spawnerData = new Spawner_FromEntity
{
// The referenced prefab will be converted due to DeclareReferencedPrefabs.
// So here we simply map the game object to an entity reference to that prefab.
Prefab = conversionSystem.GetPrimaryEntity(Prefab),
CountX = CountX,
CountY = CountY
};
dstManager.AddComponentData(entity, spawnerData);
}
}
获得数据Entity后,再通过ComponentSystem进行生成的 *** 作。由于只生成一次,在Foreach中生成一次后,直接DetroyEntity,保证不会再继续生成。
生成与移除只能在主线程中 *** 作(Entities.ForEach()等方法)。
// Systems can schedule work to run on worker threads.
// However, creating and removing Entities can only be done on the main thread to prevent race conditions.
// The system uses an EntityCommandBuffer to defer tasks that can't be done inside the Job.
public partial class SpawnerSystem_FromEntity : SystemBase
{
// BeginInitializationEntityCommandBufferSystem is used to create a command buffer which will then be played back
// when that barrier system executes.
// Though the instantiation command is recorded in the SpawnJob, it's not actually processed (or "played back")
// until the corresponding EntityCommandBufferSystem is updated. To ensure that the transform system has a chance
// to run on the newly-spawned entities before they're rendered for the first time, the SpawnerSystem_FromEntity
// will use the BeginSimulationEntityCommandBufferSystem to play back its commands. This introduces a one-frame lag
// between recording the commands and instantiating the entities, but in practice this is usually not noticeable.
BeginInitializationEntityCommandBufferSystem m_EntityCommandBufferSystem;
protected override void OnCreate()
{
// Cache the BeginInitializationEntityCommandBufferSystem in a field, so we don't have to create it every frame
m_EntityCommandBufferSystem = World.GetOrCreateSystem<BeginInitializationEntityCommandBufferSystem>();
}
protected override void OnUpdate()
{
//Instead of performing structural changes directly, a Job can add a command to an EntityCommandBuffer to perform such changes on the main thread after the Job has finished.
//Command buffers allow you to perform any, potentially costly, calculations on a worker thread, while queuing up the actual insertions and deletions for later.
var commandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().AsParallelWriter();
// Schedule the Entities.ForEach lambda job that will add Instantiate commands to the EntityCommandBuffer.
// Since this job only runs on the first frame, we want to ensure Burst compiles it before running to get the best performance (3rd parameter of WithBurst)
// The actual job will be cached once it is compiled (it will only get Burst compiled once).
Entities
.WithName("SpawnerSystem_FromEntity")
.WithBurst(FloatMode.Default, FloatPrecision.Standard, true)
.ForEach((Entity entity, int entityInQueryIndex, in Spawner_FromEntity spawnerFromEntity, in LocalToWorld location) =>
{
for (var x = 0; x < spawnerFromEntity.CountX; x++)
{
for (var y = 0; y < spawnerFromEntity.CountY; y++)
{
var instance = commandBuffer.Instantiate(entityInQueryIndex, spawnerFromEntity.Prefab);
// Place the instantiated in a grid with some noise
var position = math.transform(location.Value,
new float3(x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F));
commandBuffer.SetComponent(entityInQueryIndex, instance, new Translation {Value = position});
}
}
commandBuffer.DestroyEntity(entityInQueryIndex, entity);
}).ScheduleParallel();
// SpawnJob runs in parallel with no sync point until the barrier system executes.
// When the barrier system executes we want to complete the SpawnJob and then play back the commands (Creating the entities and placing them).
// We need to tell the barrier system which job it needs to complete before it can play back the commands.
m_EntityCommandBufferSystem.AddJobHandleForProducer(Dependency);
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)