ECS入门 4.SpawnFromEntity

9 篇文章 0 订阅

前言

此示例演示了使用预制件游戏对象生成实体和组件的不同方法。与前面的示例一样,场景生成了成对的旋转立方体的“字段”。

它显示了什么?

在前面的示例中,实体的生成方式有两个主要区别:

  1. 在此示例中,预制件游戏对象由SpawnerAuthoring_FromEntity的MonoBehaviour转换为实体表示形式,采用其“转换游戏对象实体”方法。
  2. 该示例使用作业系统来生成实体,而不是使用MonoBehaviour中的 Start() 方法。

生成实体

组件数据可以具有对其他实体的引用。在本例中,我们有一个对实体预制件的引用。与游戏对象类似,在实例化和销毁预制件时,整个预制件将作为一个组进行克隆或删除。
这样,您就可以使用系统和组件数据编写所有运行时代码。
SpawnerSystem_FromEntity查找所有Spawner_FromEntity组件。
当它找到一个时,系统实例化网格中的预制件,然后销毁生成器实体(因此它只生成一组给定的实体一次)。
SpawnerSystem_FromEntity使用实体Entities.ForEach,它与前面示例中演示的非常相似。不同之处在于,此实体对象(以及查询中的实体索引)提供给您的 lambda。实体对象是必需的,以便系统可以在处理生成器实体后将其销毁。
目前,批量创建大量实体的最有效方法是使用EntityManager.Instanceiate() 批量实例化预制件的所有副本,然后使用并行作业提供每个实例的初始组件值。

项目

场景布置

场景布置

代码编写

创建三个脚本
Spawner_FromEntity.cs

using Unity.Entities;

public struct Spawner_FromEntity : IComponentData
{
    public int CountX;
    public int CountY;
    public Entity Prefab;
}

SpawnerAuthoring_FromEntity.cs

using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;

// ReSharper disable once InconsistentNaming
[AddComponentMenu("DOTS Samples/SpawnFromEntity/Spawner")]
[ConverterVersion("joe", 1)]
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);
    }
}

SpawnerSystem_FromEntity.cs

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Entities.CodeGeneratedJobForEach;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;

// 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 demonstrates an efficient way to batch-instantiate and apply initial transformations to a large
// number of entities.
// 该系统演示了一种对大量实体进行批量实例化和应用初始转换的有效方法。
// ReSharper disable once InconsistentNaming
[UpdateInGroup(typeof(SimulationSystemGroup))]
public partial class SpawnerSystem_FromEntity : SystemBase
{
    [BurstCompile]
    struct SetSpawnedTranslation : IJobParallelFor
    {
        //禁用并行用于限制
        [NativeDisableParallelForRestriction]
        public ComponentDataFromEntity<Translation> TranslationFromEntity;

        public NativeArray<Entity> Entities;
        public float4x4 LocalToWorld;
        public int Stride;

        public void Execute(int i)
        {
            var entity = Entities[i];
            var y = i / Stride; 
            var x = i - (y * Stride);

            TranslationFromEntity[entity] = new Translation()
            {
                Value = math.transform(LocalToWorld, new float3(x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F))
            };
        }
    }

    protected override void OnUpdate()
    {
        Entities.WithStructuralChanges().ForEach((Entity entity, int entityInQueryIndex,
            in Spawner_FromEntity spawnerFromEntity, in LocalToWorld spawnerLocalToWorld) =>
        {
            Dependency.Complete();

            var spawnedCount = spawnerFromEntity.CountX * spawnerFromEntity.CountY;
            var spawnedEntities =
                new NativeArray<Entity>(spawnedCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            EntityManager.Instantiate(spawnerFromEntity.Prefab, spawnedEntities);
            EntityManager.DestroyEntity(entity);

            var translationFromEntity = GetComponentDataFromEntity<Translation>();
            var setSpawnedTranslationJob = new SetSpawnedTranslation
            {
                TranslationFromEntity = translationFromEntity,
                Entities = spawnedEntities,
                LocalToWorld = spawnerLocalToWorld.Value,
                Stride = spawnerFromEntity.CountX
            };
            Dependency = setSpawnedTranslationJob.Schedule(spawnedCount, 64, Dependency);
            Dependency = spawnedEntities.Dispose(Dependency);
        }).Run();
    }
}

添加并设置脚本

场景布置
添加组件

总结

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);
    }
}

运行效果

运行效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值