• ECS入门 4.SpawnFromEntity


    前言

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

    它显示了什么?

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

    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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    添加并设置脚本

    场景布置
    添加组件

    总结

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    运行效果

    运行效果

  • 相关阅读:
    Python语言概述
    CST--如何在PCB三维模型中自由创建离散端口
    Linux安装MySQL(源码安装)
    MySQL十秒插入百万条数据
    ExtJS类成员-判断浏览器版本和操作系统类型功能
    [LeetCode解题报告] 2376. 统计特殊整数
    Win10鼠标右键菜单不显示怎么办?
    全新升级的AOP框架Dora.Interception[2]: 基于约定的拦截器定义方式
    蔚来杯2022牛客暑期多校训练营4
    数组的使用
  • 原文地址:https://blog.csdn.net/a71468293a/article/details/127568259