Пример #1
0
        protected override void OnUpdate()
        {
            Entities.ForEach((Entity e, SpawnRandomInSphere spawner, ref LocalToWorld localToWorld) =>
            {
                int toSpawnCount = spawner.Count;

                var spawnPositions = new NativeArray <float3>(toSpawnCount, Allocator.TempJob);
                GeneratePoints.RandomPointsInUnitSphere(spawnPositions);

                // Calling Instantiate once per spawned Entity is rather slow, and not recommended
                // This code is placeholder until we add the ability to bulk-instantiate many entities from an ECB
                var entities = new NativeArray <Entity>(toSpawnCount, Allocator.Temp);
                for (int i = 0; i < toSpawnCount; ++i)
                {
                    entities[i] = PostUpdateCommands.Instantiate(spawner.Prefab);
                }

                for (int i = 0; i < toSpawnCount; i++)
                {
                    PostUpdateCommands.SetComponent(entities[i], new LocalToWorld
                    {
                        Value = float4x4.TRS(
                            localToWorld.Position + (spawnPositions[i] * spawner.Radius),
                            quaternion.LookRotationSafe(spawnPositions[i], math.up()),
                            new float3(1.0f, 1.0f, 1.0f))
                    });
                }

                PostUpdateCommands.RemoveComponent <SpawnRandomInSphere>(e);

                spawnPositions.Dispose();
                entities.Dispose();
            });
        }
Пример #2
0
        protected override void OnUpdate()
        {
            Entities.ForEach((Entity e, SpawnRandomInSphere spawner, ref LocalToWorld localToWorld) =>
            {
                int toSpawnCount = spawner.Count;

                // Using a .TempJob instead of a .Temp for `spawnPositions`, because the method
                // `RandomPointsInUnitSphere` passes this NativeArray into a Job
                var spawnPositions = new NativeArray <float3>(toSpawnCount, Allocator.TempJob);
                GeneratePoints.RandomPointsInUnitSphere(spawnPositions);

                // Calling Instantiate once per spawned Entity is rather slow, and not recommended
                // This code is placeholder until we add the ability to bulk-instantiate many entities from an ECB
                var entities = new NativeArray <Entity>(toSpawnCount, Allocator.Temp);
                for (int i = 0; i < toSpawnCount; ++i)
                {
                    entities[i] = PostUpdateCommands.Instantiate(spawner.Prefab);
                }

                for (int i = 0; i < toSpawnCount; i++)
                {
                    PostUpdateCommands.SetComponent(entities[i], new LocalToWorld
                    {
                        Value = float4x4.TRS(
                            localToWorld.Position + (spawnPositions[i] * spawner.Radius),
                            quaternion.LookRotationSafe(spawnPositions[i], math.up()),
                            new float3(1.0f, 1.0f, 1.0f))
                    });
                }

                // Using 'RemoveComponent' instead of 'DestroyEntity' as a safety.
                // Removing the SpawnRandomInSphere component is sufficient to prevent the spawner
                // from executing its spawn logic more than once. The spawner may have other components
                // that are relevant to ongoing processing; this system doesn't know about them & shouldn't
                // assume the entity is safe to delete.
                PostUpdateCommands.RemoveComponent <SpawnRandomInSphere>(e);

                spawnPositions.Dispose();
                entities.Dispose();
            });
        }
        protected override void OnUpdate()
        {
            var uniqueTypes = new List <SpawnRandomInSphere>(10);

            EntityManager.GetAllUniqueSharedComponentData(uniqueTypes);

            int spawnInstanceCount = 0;

            for (int sharedIndex = 0; sharedIndex != uniqueTypes.Count; sharedIndex++)
            {
                var spawner = uniqueTypes[sharedIndex];
                m_MainGroup.SetFilter(spawner);
                var entityCount = m_MainGroup.CalculateLength();
                spawnInstanceCount += entityCount;
            }

            if (spawnInstanceCount == 0)
            {
                return;
            }

            var spawnInstances = new NativeArray <SpawnRandomInSphereInstance>(spawnInstanceCount, Allocator.Temp);

            {
                int spawnIndex = 0;
                for (int sharedIndex = 0; sharedIndex != uniqueTypes.Count; sharedIndex++)
                {
                    var spawner = uniqueTypes[sharedIndex];
                    m_MainGroup.SetFilter(spawner);

                    if (m_MainGroup.CalculateLength() == 0)
                    {
                        continue;
                    }

                    var entities     = m_MainGroup.ToEntityArray(Allocator.TempJob);
                    var localToWorld = m_MainGroup.ToComponentDataArray <LocalToWorld>(Allocator.TempJob);

                    for (int entityIndex = 0; entityIndex < entities.Length; entityIndex++)
                    {
                        var spawnInstance = new SpawnRandomInSphereInstance();

                        spawnInstance.sourceEntity = entities[entityIndex];
                        spawnInstance.spawnerIndex = sharedIndex;
                        spawnInstance.position     = localToWorld[entityIndex].Position;

                        spawnInstances[spawnIndex] = spawnInstance;
                        spawnIndex++;
                    }

                    entities.Dispose();
                    localToWorld.Dispose();
                }
            }

            for (int spawnIndex = 0; spawnIndex < spawnInstances.Length; spawnIndex++)
            {
                int    spawnerIndex   = spawnInstances[spawnIndex].spawnerIndex;
                var    spawner        = uniqueTypes[spawnerIndex];
                int    count          = spawner.count;
                var    entities       = new NativeArray <Entity>(count, Allocator.Temp);
                var    prefab         = spawner.prefab;
                float  radius         = spawner.radius;
                var    spawnPositions = new NativeArray <float3>(count, Allocator.TempJob);
                float3 center         = spawnInstances[spawnIndex].position;
                var    sourceEntity   = spawnInstances[spawnIndex].sourceEntity;

                GeneratePoints.RandomPointsInUnitSphere(spawnPositions);

                EntityManager.Instantiate(prefab, entities);

                for (int i = 0; i < count; i++)
                {
                    EntityManager.SetComponentData(entities[i], new LocalToWorld
                    {
                        Value = float4x4.TRS(
                            center + (spawnPositions[i] * radius),
                            quaternion.LookRotationSafe(spawnPositions[i], math.up()),
                            new float3(1.0f, 1.0f, 1.0f))
                    });
                }

                EntityManager.RemoveComponent <SpawnRandomInSphere>(sourceEntity);

                spawnPositions.Dispose();
                entities.Dispose();
            }
            spawnInstances.Dispose();
        }
        // This is (most times) a trigger: see https://forum.unity.com/threads/onupdate-method-in-componentsystems.541647/ for when it's called
        protected override void OnUpdate()
        {
            var uniqueTypes = new List <SpawnRandomInSphere>(10);

            // We have (by default) 2 BoidFishSpawners in the scene (if not modified). These have 3 attributes. If both spawners have EXACTLY the same values (whether its reference or value type)
            // they will be "fused" in uniqueTypes.Count, so uniqueTypes.Count will be 2, otherwise it'll be 3. The reason is that the first seems to be a default one (see link below)
            EntityManager.GetAllUniqueSharedComponentData(uniqueTypes);

            int spawnInstanceCount = 0;

            // https://forum.unity.com/threads/question-about-getalluniquesharedcomponentdata.545945/
            // Since the 0 is the default, why not start at 1, does not make any difference since when filtering by the 0 uniqueType, it's being ignored
            for (int sharedIndex = 0 /* 1 */; sharedIndex != uniqueTypes.Count; sharedIndex++)
            {
                var spawner = uniqueTypes[sharedIndex];

                // this is filtering the "groups of instances" that have the same values
                m_MainGroup.SetFilter(spawner);

                // we're counting them
                var entityCount = m_MainGroup.CalculateLength();

                // so this is the overall number of instances wether or not they have the same values
                spawnInstanceCount += entityCount;
            }

            if (spawnInstanceCount == 0)
            {
                return;
            }

            var spawnInstances = new NativeArray <SpawnRandomInSphereInstance>(spawnInstanceCount, Allocator.Temp);

            {
                int spawnIndex = 0;
                for (int sharedIndex = 0; sharedIndex != uniqueTypes.Count; sharedIndex++)
                {
                    var spawner = uniqueTypes[sharedIndex];
                    m_MainGroup.SetFilter(spawner);

                    // this would never be 0 if the previous loop started at 1 I guess
                    if (m_MainGroup.CalculateLength() == 0)
                    {
                        continue;
                    }

                    // 1+1 entities (if any value differs, and it is the default scene, 2 spawners overall)
                    var entities = m_MainGroup.ToEntityArray(Allocator.TempJob);

                    var localToWorld = m_MainGroup.ToComponentDataArray <LocalToWorld>(Allocator.TempJob);

                    // convenient way of storing the 2 (if default) spawners info
                    for (int entityIndex = 0; entityIndex < entities.Length; entityIndex++)
                    {
                        var spawnInstance = new SpawnRandomInSphereInstance();

                        spawnInstance.sourceEntity = entities[entityIndex];
                        spawnInstance.spawnerIndex = sharedIndex;
                        spawnInstance.position     = localToWorld[entityIndex].Position;

                        spawnInstances[spawnIndex] = spawnInstance;
                        spawnIndex++;
                    }

                    entities.Dispose();
                    localToWorld.Dispose();
                }

                // for more info about ISharedComponentData see: https://docs.unity3d.com/Packages/[email protected]/manual/shared_component_data.html
            }

            // now for every spawner
            for (int spawnIndex = 0; spawnIndex < spawnInstances.Length; spawnIndex++)
            {
                int    spawnerIndex = spawnInstances[spawnIndex].spawnerIndex;
                var    spawner      = uniqueTypes[spawnerIndex];
                int    count        = spawner.count;
                var    prefab       = spawner.prefab;
                float  radius       = spawner.radius;
                float3 center       = spawnInstances[spawnIndex].position;
                var    sourceEntity = spawnInstances[spawnIndex].sourceEntity;

                var spawnPositions = new NativeArray <float3>(count, Allocator.TempJob);
                var entities       = new NativeArray <Entity>(count, Allocator.Temp);

                // prepare the positions to spawn the fishes and instantiate them
                GeneratePoints.RandomPointsInUnitSphere(spawnPositions);
                EntityManager.Instantiate(prefab, entities);

                for (int i = 0; i < count; i++)
                {
                    // set the fishes entities data
                    EntityManager.SetComponentData(entities[i], new LocalToWorld
                    {
                        // the center is the spawner GameObject center
                        // radius is the sphere radius
                        Value = float4x4.TRS(
                            center + (spawnPositions[i] * radius),
                            quaternion.LookRotationSafe(spawnPositions[i], math.up()),
                            new float3(1.0f, 1.0f, 1.0f))
                    });
                }

                // the system does not need it anymore, get rid of it
                EntityManager.RemoveComponent <SpawnRandomInSphere>(sourceEntity);

                spawnPositions.Dispose();
                entities.Dispose();
            }
            spawnInstances.Dispose();
        }