Example #1
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var projectileTranslations = m_projectilesQuery.ToComponentDataArray <Translation>(Allocator.TempJob);
        var projectileCollisions   = m_projectilesQuery.ToComponentDataArray <CollisionSize>(Allocator.TempJob);
        var projectiles            = m_projectilesQuery.ToEntityArray(Allocator.TempJob);

        poolLocations.Clear();
        EntityManager.GetAllUniqueSharedComponentData <ProjectilePoolLocation>(poolLocations);

        if (projectileCollisions.Length > 0 && poolLocations.Count > 1)
        {
            var job = new ProjectileCollisionJob
            {
                ProjectileTranslations = projectileTranslations,
                ProjectileCollisions   = projectileCollisions,
                Projectiles            = projectiles,
                ECB          = m_beginSimEcbSystem.CreateCommandBuffer().ToConcurrent(),
                PoolLocation = poolLocations[1].Value
            };

            inputDeps = job.Schedule(this, inputDeps);
            m_projectilesQuery.AddDependency(inputDeps);
            m_beginSimEcbSystem.AddJobHandleForProducer(inputDeps);
        }
        else
        {
            projectileTranslations.Dispose();
            projectileCollisions.Dispose();
            projectiles.Dispose();
        }

        return(inputDeps);
    }
    protected override JobHandle OnUpdate(JobHandle job)
    {
        spawnerTypes_.Clear();

        EntityManager.GetAllUniqueSharedComponentData(spawnerTypes_);

        // Ignore 0 (prefab == Entity.null)
        for (int i = 1; i < spawnerTypes_.Count; ++i)
        {
            spawnerQuery_.SetFilter(spawnerTypes_[i]);

            //Debug.Log("Running shooter job");
            job = new AutoBulletShooterSystemJob
            {
                commandBuffer = initBufferSystem_.CreateCommandBuffer().ToConcurrent(),
                bulletPrefab  = spawnerTypes_[i].bulletPrefab,
                dt            = Time.deltaTime,
            }.Schedule(spawnerQuery_, job);

            initBufferSystem_.AddJobHandleForProducer(job);

            spawnerQuery_.AddDependency(job);
        }

        return(job);
    }
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var job = new ScaleJob();

        JobHandle jobHandler = job.Schedule(entitiesScaleGroup, inputDeps);

        entitiesScaleGroup.AddDependency(inputDeps);

        return(jobHandler);
    }
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            var agentCount = agentQuery.CalculateEntityCount();

            if (agentCount == 0)
            {
                agentQuery.ResetFilter();
                return(inputDeps);
            }

            var hashMap         = new NativeMultiHashMap <int, int>(agentCount, Allocator.TempJob);
            var parallelHashMap = hashMap.AsParallelWriter();

            var hashJob = Entities
                          .WithNone <NavAvoidant, NavPlanning>()
                          .WithAll <NavLerping, Parent, LocalToParent>()
                          .WithNativeDisableContainerSafetyRestriction(parallelHashMap)
                          .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
            {
                parallelHashMap.Add(
                    (int)math.hash(new int3(math.floor(localToWorld.Position / NavConstants.AVOIDANCE_CELL_RADIUS))),
                    entityInQueryIndex
                    );
            })
                          .WithName("NavHashJob")
                          .Schedule(inputDeps);

            agentQuery.AddDependency(hashJob);
            agentQuery.ResetFilter();

            var avoidJob = new AvoidJob
            {
                DeltaSeconds           = Time.DeltaTime,
                AgentEntityArray       = agentQuery.ToEntityArray(Allocator.TempJob),
                AgentFromEntity        = GetComponentDataFromEntity <NavAgent>(),
                RotationFromEntity     = GetComponentDataFromEntity <Rotation>(true),
                LocalToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true),
                ParentFromEntity       = GetComponentDataFromEntity <Parent>(true),
                PathBufferFromEntity   = GetBufferFromEntity <NavPathBufferElement>(true),
                CommandBuffer          = barrier.CreateCommandBuffer().ToConcurrent()
            }.Schedule(hashMap, 64, hashJob);

            avoidJob = hashMap.Dispose(avoidJob);
            barrier.AddJobHandleForProducer(avoidJob);

            return(avoidJob);
        }
Example #5
0
        protected override void OnUpdate()
        {
            particleQuery.AddDependency(Dependency);
            int entityCount = particleQuery.CalculateEntityCount();

            // Do a sweap over all the entities and extract an entity which matches the "world" they are in
            // and also convert their locations to a 2D position on the grid
            var sharedEntityDetails = new NativeArray <Entity>(entityCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var entityLocations     = new NativeArray <float2>(entityCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var groupEntitiesJob = Entities
                                   .WithStoreEntityQueryInField(ref particleQuery)
                                   .WithName("GrabParticleSpawnInfo")
                                   .ForEach((in int entityInQueryIndex, in NewLife lifeDetails, in Translation location) =>
            {
                sharedEntityDetails[entityInQueryIndex] = lifeDetails.worldEntity;
                entityLocations[entityInQueryIndex]     = new float2(location.Value.x, location.Value.z);
            }).ScheduleParallel(Dependency);
Example #6
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            EntityCommandBuffer.Concurrent commandBuffer = endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
            BoundingVolume playerBounds = GetComponentDataFromEntity <BoundingVolume>(true)[GameHandler.playerEntity];
            Health         playerHealth = GetComponentDataFromEntity <Health>(true)[GameHandler.playerEntity];
            Player         player       = GetComponentDataFromEntity <Player>(true)[GameHandler.playerEntity];

            PlayerToHealthModifierCollisionJob pToHJob = new PlayerToHealthModifierCollisionJob()
            {
                player        = GameHandler.playerEntity,
                playerBounds  = playerBounds.volume,
                playerHealth  = playerHealth,
                commandBuffer = commandBuffer
            };
            JobHandle jobHandle = pToHJob.Schedule(this, inputDeps);

            EntityQuery bulletQuery = EntityManager.CreateEntityQuery(typeof(Bullet), ComponentType.ReadOnly <BoundingVolume>(), ComponentType.ReadOnly <HealthModifier>());

            bulletQuery.AddDependency(jobHandle);

            BulletToDamageableCollisionJob bToDam = new BulletToDamageableCollisionJob()
            {
                commandBuffer    = commandBuffer,
                bulletColliders  = bulletQuery.ToComponentDataArray <BoundingVolume>(Allocator.TempJob),
                bulletHealthMods = bulletQuery.ToComponentDataArray <HealthModifier>(Allocator.TempJob),
                bulletInfos      = bulletQuery.ToComponentDataArray <Bullet>(Allocator.TempJob),
                bullets          = bulletQuery.ToEntityArray(Allocator.TempJob)
            };

            jobHandle = bToDam.Schedule(this, jobHandle);

            ValidateLifeJob validateLifeJob = new ValidateLifeJob()
            {
                playerEntity  = GameHandler.playerEntity,
                player        = player,
                commandBuffer = commandBuffer
            };

            jobHandle = validateLifeJob.Schedule(this, jobHandle);

            endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(jobHandle);
            return(jobHandle);
        }
Example #7
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        t += Bootstrap.Instance.speed * Time.deltaTime;

        var job = new LoopAnimationJob()
        {
            Time         = t,
            ShapeRadius  = Bootstrap.Instance.shapeRadius,
            ShapeSides   = Bootstrap.Instance.shapeSides,
            SideSize     = Bootstrap.Instance.sideSize,
            Radius       = Bootstrap.Instance.radius,
            Rings        = Bootstrap.Instance.rings,
            CubesPerRing = Bootstrap.Instance.cubesPerRing
        };

        JobHandle jobHandler = job.Schedule(entitiesTransformGroup, inputDeps);

        entitiesTransformGroup.AddDependency(inputDeps);

        return(jobHandler);
    }
Example #8
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        BoidActionSort    boidActionsSort   = new BoidActionSort();
        NonBoidActionSort nonBoidActionSort = new NonBoidActionSort();

        EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes);

        int obstacleCount = m_ObstacleGroup.CalculateLength();
        int targetCount   = m_TargetGroup.CalculateLength();

        // Ingore typeIndex 0, can't use the default for anything meaningful.
        for (int typeIndex = 1; typeIndex < m_UniqueTypes.Count; typeIndex++)
        {
            MainBoid uniqueBoidConfig = m_UniqueTypes[typeIndex];
            m_BoidGroup.SetFilter(uniqueBoidConfig);

            int boidCount = m_BoidGroup.CalculateLength();
            //some of this can be cached from last time to reduce component data calls.
            int cacheIndex = typeIndex - 1;
            //this was causing an undisposed allocation error
            //NativeArray<JobHandle> initializationJobHandles = new NativeArray<JobHandle>(5, Allocator.Temp);

            NativeArray <Heading> boidHeadings = m_BoidGroup.ToComponentDataArray <Heading>(Allocator.TempJob, out JobHandle initialCellAlignmentJobHandle);
            //TODO: make this into a 2d array so that the 2d positions doesnt have to be calculated all the time.
            NativeArray <Translation> boidPositions         = m_BoidGroup.ToComponentDataArray <Translation>(Allocator.TempJob, out JobHandle initialCellSeparationJobHandle);
            NativeArray <Translation> copyTargetPositions   = m_TargetGroup.ToComponentDataArray <Translation>(Allocator.TempJob, out JobHandle copyTargetPositionsJobHandle);
            NativeArray <Translation> copyObstaclePositions = m_ObstacleGroup.ToComponentDataArray <Translation>(Allocator.TempJob, out JobHandle copyObstaclePositionsJobHandle);
            //  initializationJobHandles[0] = initialCellAlignmentJobHandle;
            //    initializationJobHandles[1] = initialCellSeparationJobHandle;
            //   initializationJobHandles[2] = copyTargetPositionsJobHandle;
            //    initializationJobHandles[3] = copyObstaclePositionsJobHandle;

            NativeArray <BoidAction> orderedBoidActions = new NativeArray <BoidAction>(uniqueBoidConfig.boidActions.Length, Allocator.TempJob);
            orderedBoidActions.CopyFrom(uniqueBoidConfig.boidActions);

            NativeArray <NonBoidAction> orderedNonBoidActions = new NativeArray <NonBoidAction>(uniqueBoidConfig.boidActions.Length, Allocator.TempJob);
            orderedBoidActions.CopyFrom(uniqueBoidConfig.boidActions);

            orderedNonBoidActions.Sort(nonBoidActionSort);
            orderedBoidActions.Sort(boidActionsSort);

            var hashMap = new NativeHashMap <float3, int>(boidCount, Allocator.TempJob);

            var hashPositionsJob = new HashPositions
            {
                hashMap = hashMap.ToConcurrent()
            };
            var hashPositionsJobHandle = hashPositionsJob.Schedule(m_BoidGroup, inputDeps);

            //  initializationJobHandles[4] = hashPositionsJobHandle;

            var nextCells = new PrevCells
            {
                hashMap = hashMap,

                boidHeadings  = boidHeadings,
                boidPositions = boidPositions,

                copyObstaclePositions = copyObstaclePositions,
                copyTargetPositions   = copyTargetPositions,

                orderedBoidActions    = orderedBoidActions,
                orderedNonBoidActions = orderedNonBoidActions,
            };
            if (cacheIndex > (m_PrevCells.Count - 1))
            {
                m_PrevCells.Add(nextCells);
            }
            else
            {
                m_PrevCells[cacheIndex].hashMap.Dispose();

                m_PrevCells[cacheIndex].copyTargetPositions.Dispose();
                m_PrevCells[cacheIndex].copyObstaclePositions.Dispose();

                m_PrevCells[cacheIndex].boidHeadings.Dispose();
                m_PrevCells[cacheIndex].boidPositions.Dispose();

                m_PrevCells[cacheIndex].orderedBoidActions.Dispose();
                m_PrevCells[cacheIndex].orderedNonBoidActions.Dispose();
            }
            m_PrevCells[cacheIndex] = nextCells;

            JobHandle initialCellBarrierJobHandle        = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, copyTargetPositionsJobHandle);
            JobHandle copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(initialCellBarrierJobHandle, copyObstaclePositionsJobHandle, hashPositionsJobHandle);

            Steer steerJob = new Steer
            {
                //                boidActionFunctions = boidActionFunctions,
                //boidConfig = uniqueBoidConfig,
                boidIndexs            = hashMap,
                boidHeadings          = boidHeadings,
                boidPositions         = boidPositions,
                orderedBoidActions    = orderedBoidActions,
                orderedNonBoidActions = orderedNonBoidActions,
                targetPositions       = copyTargetPositions,
                obstaclePositions     = copyObstaclePositions,
                dt = Time.deltaTime
            };
            JobHandle steerJobHandle = steerJob.Schedule(m_BoidGroup, copyTargetObstacleBarrierJobHandle);

            inputDeps = steerJobHandle;
            m_BoidGroup.AddDependency(inputDeps);
        }
        m_UniqueTypes.Clear();

        return(inputDeps);
    }
    protected override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        EntityManager.GetAllUniqueSharedComponentData(uniqueTypes);

        var obstacleCount = obstacleQuery.CalculateEntityCount();
        var targetCount   = targetQuery.CalculateEntityCount();

        for (int i = 0; i < prevFrameHashmaps.Count; i++)
        {
            prevFrameHashmaps[i].Dispose();
        }
        prevFrameHashmaps.Clear();

        for (int hordeVariantIndex = 0; hordeVariantIndex < uniqueTypes.Count; hordeVariantIndex++)
        {
            var settings = uniqueTypes[hordeVariantIndex];
            hordeQuery.SetFilter(settings);
            var hordeCount = hordeQuery.CalculateEntityCount();

            if (hordeCount == 0)
            {
                continue;
            }
            //Debug.Log(hordeCount);

            #region Initial vars

            var hashMap = new NativeMultiHashMap <int, int>(hordeCount, Allocator.TempJob);

            var cellIndices = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var cellObstaclePositionIndex = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var cellTargetPositionIndex   = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var cellCount = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var cellObstacleDistance = new NativeArray <float>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var cellAlignment        = new NativeArray <float3>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var cellSeparation       = new NativeArray <float3>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var copyTargetPositions   = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            #endregion

            #region Initial jobs

            var initialCellAlignmentJob = new CopyHeadings {
                headings = cellAlignment
            };
            var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(hordeQuery, inputDependencies);

            var initialCellSeparationJob = new CopyPositions {
                positions = cellSeparation
            };
            var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(hordeQuery, inputDependencies);

            var copyTargetPositionsJob = new CopyPositions {
                positions = copyTargetPositions
            };
            var copyTargetPositionsJobHandle = copyTargetPositionsJob.Schedule(targetQuery, inputDependencies);

            var copyObstaclePositionsJob = new CopyPositions {
                positions = copyObstaclePositions
            };
            var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(obstacleQuery, inputDependencies);

            prevFrameHashmaps.Add(hashMap);

            var hashPositionsJob = new HashPositions
            {
                hashMap    = hashMap.AsParallelWriter(),
                cellRadius = settings.CellRadius
            };
            var hashPositionsJobHandle = hashPositionsJob.Schedule(hordeQuery, inputDependencies);

            var initialCellCountJob = new MemsetNativeArray <int>
            {
                Source = cellCount,
                Value  = 1
            };
            var initialCellCountJobHandle = initialCellCountJob.Schedule(hordeCount, 64, inputDependencies);

            #endregion

            var initialCellBarrierJobHandle        = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle);
            var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle);
            var mergeCellsBarrierJobHandle         = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle);

            var mergeCellsJob = new MergeCells
            {
                cellIndices               = cellIndices,
                cellAlignment             = cellAlignment,
                cellSeparation            = cellSeparation,
                cellObstacleDistance      = cellObstacleDistance,
                cellObstaclePositionIndex = cellObstaclePositionIndex,
                cellTargetPositionIndex   = cellTargetPositionIndex,
                cellCount         = cellCount,
                targetPositions   = copyTargetPositions,
                obstaclePositions = copyObstaclePositions
            };
            var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle);

            var steerJob = new Steer
            {
                cellIndices               = cellIndices,
                settings                  = settings,
                cellAlignment             = cellAlignment,
                cellSeparation            = cellSeparation,
                cellObstacleDistance      = cellObstacleDistance,
                cellObstaclePositionIndex = cellObstaclePositionIndex,
                cellTargetPositionIndex   = cellTargetPositionIndex,
                cellCount                 = cellCount,
                targetPositions           = copyTargetPositions,
                obstaclePositions         = copyObstaclePositions,
                dt = Time.deltaTime,
            };
            var steerJobHandle = steerJob.Schedule(hordeQuery, mergeCellsJobHandle);

            inputDependencies = steerJobHandle;
            hordeQuery.AddDependency(inputDependencies);
        }
        uniqueTypes.Clear();

        return(inputDependencies);
    }
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes);

            var obstacleCount = m_ObstacleGroup.CalculateLength();
            var targetCount   = m_TargetGroup.CalculateLength();

            // Ignore typeIndex 0, can't use the default for anything meaningful.
            for (int typeIndex = 1; typeIndex < m_UniqueTypes.Count; typeIndex++)
            {
                var settings = m_UniqueTypes[typeIndex];
                m_BoidGroup.SetFilter(settings);

                var boidCount = m_BoidGroup.CalculateLength();

                var cacheIndex                = typeIndex - 1;
                var cellIndices               = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var hashMap                   = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);
                var cellObstacleDistance      = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellObstaclePositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellTargetPositionIndex   = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellCount                 = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);


                var cellAlignment = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                             NativeArrayOptions.UninitializedMemory);
                var cellSeparation = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                              NativeArrayOptions.UninitializedMemory);
                var copyTargetPositions = new NativeArray <float3>(targetCount, Allocator.TempJob,
                                                                   NativeArrayOptions.UninitializedMemory);
                var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob,
                                                                     NativeArrayOptions.UninitializedMemory);

                var initialCellAlignmentJob = new CopyHeadings
                {
                    headings = cellAlignment
                };
                var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(m_BoidGroup, inputDeps);

                var initialCellSeparationJob = new CopyPositions
                {
                    positions = cellSeparation
                };
                var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(m_BoidGroup, inputDeps);

                var copyTargetPositionsJob = new CopyPositions
                {
                    positions = copyTargetPositions
                };
                var copyTargetPositionsJobHandle = copyTargetPositionsJob.Schedule(m_TargetGroup, inputDeps);

                var copyObstaclePositionsJob = new CopyPositions
                {
                    positions = copyObstaclePositions
                };
                var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(m_ObstacleGroup, inputDeps);

                var nextCells = new PrevCells
                {
                    cellIndices               = cellIndices,
                    hashMap                   = hashMap,
                    copyObstaclePositions     = copyObstaclePositions,
                    copyTargetPositions       = copyTargetPositions,
                    cellAlignment             = cellAlignment,
                    cellSeparation            = cellSeparation,
                    cellObstacleDistance      = cellObstacleDistance,
                    cellObstaclePositionIndex = cellObstaclePositionIndex,
                    cellTargetPositionIndex   = cellTargetPositionIndex,
                    cellCount                 = cellCount
                };

                if (cacheIndex > (m_PrevCells.Count - 1))
                {
                    m_PrevCells.Add(nextCells);
                }
                else
                {
                    m_PrevCells[cacheIndex].hashMap.Dispose();
                    m_PrevCells[cacheIndex].cellIndices.Dispose();
                    m_PrevCells[cacheIndex].cellObstaclePositionIndex.Dispose();
                    m_PrevCells[cacheIndex].cellTargetPositionIndex.Dispose();
                    m_PrevCells[cacheIndex].copyTargetPositions.Dispose();
                    m_PrevCells[cacheIndex].copyObstaclePositions.Dispose();
                    m_PrevCells[cacheIndex].cellAlignment.Dispose();
                    m_PrevCells[cacheIndex].cellSeparation.Dispose();
                    m_PrevCells[cacheIndex].cellObstacleDistance.Dispose();
                    m_PrevCells[cacheIndex].cellCount.Dispose();
                }
                m_PrevCells[cacheIndex] = nextCells;

                var hashPositionsJob = new HashPositions
                {
                    hashMap    = hashMap.ToConcurrent(),
                    cellRadius = settings.CellRadius
                };
                var hashPositionsJobHandle = hashPositionsJob.Schedule(m_BoidGroup, inputDeps);

                var initialCellCountJob = new MemsetNativeArray <int>
                {
                    Source = cellCount,
                    Value  = 1
                };
                var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDeps);

                var initialCellBarrierJobHandle        = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle);
                var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle);
                var mergeCellsBarrierJobHandle         = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle);

                var mergeCellsJob = new MergeCells
                {
                    cellIndices               = cellIndices,
                    cellAlignment             = cellAlignment,
                    cellSeparation            = cellSeparation,
                    cellObstacleDistance      = cellObstacleDistance,
                    cellObstaclePositionIndex = cellObstaclePositionIndex,
                    cellTargetPositionIndex   = cellTargetPositionIndex,
                    cellCount         = cellCount,
                    targetPositions   = copyTargetPositions,
                    obstaclePositions = copyObstaclePositions
                };
                var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle);

                var steerJob = new Steer
                {
                    cellIndices               = nextCells.cellIndices,
                    settings                  = settings,
                    cellAlignment             = cellAlignment,
                    cellSeparation            = cellSeparation,
                    cellObstacleDistance      = cellObstacleDistance,
                    cellObstaclePositionIndex = cellObstaclePositionIndex,
                    cellTargetPositionIndex   = cellTargetPositionIndex,
                    cellCount                 = cellCount,
                    targetPositions           = copyTargetPositions,
                    obstaclePositions         = copyObstaclePositions,
                    dt = Time.deltaTime,
                };
                var steerJobHandle = steerJob.Schedule(m_BoidGroup, mergeCellsJobHandle);

                inputDeps = steerJobHandle;
                m_BoidGroup.AddDependency(inputDeps);
            }
            m_UniqueTypes.Clear();

            return(inputDeps);
        }
Example #11
0
    protected override void OnUpdate()
    {
        if (!m_DriverSystem.ClientDriver.IsCreated)
        {
            return;
        }
        PingClientUIBehaviour.UpdateStats(m_PingStats[0], m_PingStats[1]);
        if (PingClientUIBehaviour.ServerEndPoint.IsValid && m_ConnectionGroup.IsEmptyIgnoreFilter)
        {
            Dependency.Complete();
            var ent = EntityManager.CreateEntity();
            EntityManager.AddComponentData(ent, new PingClientConnectionComponentData {
                connection = m_DriverSystem.ClientDriver.Connect(PingClientUIBehaviour.ServerEndPoint)
            });
            return;
        }

        var driver        = m_DriverSystem.ClientDriver;
        var serverEP      = PingClientUIBehaviour.ServerEndPoint;
        var pendingPings  = m_PendingPings;
        var pingStats     = m_PingStats;
        var frameTime     = Time.ElapsedTime;
        var commandBuffer = m_Barrier.CreateCommandBuffer();

        Entities.ForEach((Entity entity, ref PingClientConnectionComponentData connection) =>
        {
            if (!serverEP.IsValid)
            {
                connection.connection.Disconnect(driver);
                commandBuffer.DestroyEntity(entity);
                return;
            }

            DataStreamReader strm;
            NetworkEvent.Type cmd;
            while ((cmd = connection.connection.PopEvent(driver, out strm)) != NetworkEvent.Type.Empty)
            {
                if (cmd == NetworkEvent.Type.Connect)
                {
                    pendingPings[0] = new PendingPing {
                        id = pingStats[0], time = frameTime
                    };

                    if (driver.BeginSend(connection.connection, out var pingData) == 0)
                    {
                        pingData.WriteInt(pingStats[0]);
                        driver.EndSend(pingData);
                    }
                    pingStats[0] = pingStats[0] + 1;
                }
                else if (cmd == NetworkEvent.Type.Data)
                {
                    pingStats[1] = (int)((frameTime - pendingPings[0].time) * 1000);
                    connection.connection.Disconnect(driver);
                    commandBuffer.DestroyEntity(entity);
                }
                else if (cmd == NetworkEvent.Type.Disconnect)
                {
                    commandBuffer.DestroyEntity(entity);
                }
            }
        }).Schedule();
        m_Barrier.AddJobHandleForProducer(Dependency);
        m_ServerConnectionGroup.AddDependency(Dependency);
    }
Example #12
0
        protected override void OnUpdate()
        {
            var obstacleCount = m_ObstacleQuery.CalculateEntityCount();
            var targetCount   = m_TargetQuery.CalculateEntityCount();

            EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes);

            // Each variant of the Boid represents a different value of the SharedComponentData and is self-contained,
            // meaning Boids of the same variant only interact with one another. Thus, this loop processes each
            // variant type individually.
            for (int boidVariantIndex = 0; boidVariantIndex < m_UniqueTypes.Count; boidVariantIndex++)
            {
                var settings = m_UniqueTypes[boidVariantIndex];
                m_BoidQuery.AddSharedComponentFilter(settings);

                var boidCount = m_BoidQuery.CalculateEntityCount();

                if (boidCount == 0)
                {
                    // Early out. If the given variant includes no Boids, move on to the next loop.
                    // For example, variant 0 will always exit early bc it's it represents a default, uninitialized
                    // Boid struct, which does not appear in this sample.
                    m_BoidQuery.ResetFilter();
                    continue;
                }

                // The following calculates spatial cells of neighboring Boids
                // note: working with a sparse grid and not a dense bounded grid so there
                // are no predefined borders of the space.

                var hashMap     = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);
                var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellObstaclePositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellTargetPositionIndex   = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellCount            = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellObstacleDistance = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellAlignment        = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellSeparation       = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                var copyTargetPositions   = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                // The following jobs all run in parallel because the same JobHandle is passed for their
                // input dependencies when the jobs are scheduled; thus, they can run in any order (or concurrently).
                // The concurrency is property of how they're scheduled, not of the job structs themselves.

                // These jobs extract the relevant position, heading component
                // to NativeArrays so that they can be randomly accessed by the `MergeCells` and `Steer` jobs.
                // These jobs are defined inline using the Entities.ForEach lambda syntax.
                var initialCellAlignmentJobHandle = Entities
                                                    .WithSharedComponentFilter(settings)
                                                    .WithName("InitialCellAlignmentJob")
                                                    .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    cellAlignment[entityInQueryIndex] = localToWorld.Forward;
                })
                                                    .ScheduleParallel(Dependency);

                var initialCellSeparationJobHandle = Entities
                                                     .WithSharedComponentFilter(settings)
                                                     .WithName("InitialCellSeparationJob")
                                                     .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    cellSeparation[entityInQueryIndex] = localToWorld.Position;
                })
                                                     .ScheduleParallel(Dependency);

                var copyTargetPositionsJobHandle = Entities
                                                   .WithName("CopyTargetPositionsJob")
                                                   .WithAll <BoidTarget>()
                                                   .WithStoreEntityQueryInField(ref m_TargetQuery)
                                                   .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    copyTargetPositions[entityInQueryIndex] = localToWorld.Position;
                })
                                                   .ScheduleParallel(Dependency);

                var copyObstaclePositionsJobHandle = Entities
                                                     .WithName("CopyObstaclePositionsJob")
                                                     .WithAll <BoidObstacle>()
                                                     .WithStoreEntityQueryInField(ref m_ObstacleQuery)
                                                     .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    copyObstaclePositions[entityInQueryIndex] = localToWorld.Position;
                })
                                                     .ScheduleParallel(Dependency);

                // Populates a hash map, where each bucket contains the indices of all Boids whose positions quantize
                // to the same value for a given cell radius so that the information can be randomly accessed by
                // the `MergeCells` and `Steer` jobs.
                // This is useful in terms of the algorithm because it limits the number of comparisons that will
                // actually occur between the different boids. Instead of for each boid, searching through all
                // boids for those within a certain radius, this limits those by the hash-to-bucket simplification.
                var parallelHashMap        = hashMap.AsParallelWriter();
                var hashPositionsJobHandle = Entities
                                             .WithName("HashPositionsJob")
                                             .WithAll <Boid>()
                                             .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    var hash = (int)math.hash(new int3(math.floor(localToWorld.Position / settings.CellRadius)));
                    parallelHashMap.Add(hash, entityInQueryIndex);
                })
                                             .ScheduleParallel(Dependency);

                var initialCellCountJob = new MemsetNativeArray <int>
                {
                    Source = cellCount,
                    Value  = 1
                };
                var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, Dependency);

                var initialCellBarrierJobHandle        = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle);
                var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle);
                var mergeCellsBarrierJobHandle         = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle);

                var mergeCellsJob = new MergeCells
                {
                    cellIndices               = cellIndices,
                    cellAlignment             = cellAlignment,
                    cellSeparation            = cellSeparation,
                    cellObstacleDistance      = cellObstacleDistance,
                    cellObstaclePositionIndex = cellObstaclePositionIndex,
                    cellTargetPositionIndex   = cellTargetPositionIndex,
                    cellCount         = cellCount,
                    targetPositions   = copyTargetPositions,
                    obstaclePositions = copyObstaclePositions
                };
                var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle);

                // This reads the previously calculated boid information for all the boids of each cell to update
                // the `localToWorld` of each of the boids based on their newly calculated headings using
                // the standard boid flocking algorithm.
                float deltaTime      = math.min(0.05f, Time.DeltaTime);
                var   steerJobHandle = Entities
                                       .WithName("Steer")
                                       .WithSharedComponentFilter(settings) // implies .WithAll<Boid>()
                                       .WithReadOnly(cellIndices)
                                       .WithReadOnly(cellCount)
                                       .WithReadOnly(cellAlignment)
                                       .WithReadOnly(cellSeparation)
                                       .WithReadOnly(cellObstacleDistance)
                                       .WithReadOnly(cellObstaclePositionIndex)
                                       .WithReadOnly(cellTargetPositionIndex)
                                       .WithReadOnly(copyObstaclePositions)
                                       .WithReadOnly(copyTargetPositions)
                                       .ForEach((int entityInQueryIndex, ref LocalToWorld localToWorld) =>
                {
                    // temporarily storing the values for code readability
                    var forward                      = localToWorld.Forward;
                    var currentPosition              = localToWorld.Position;
                    var cellIndex                    = cellIndices[entityInQueryIndex];
                    var neighborCount                = cellCount[cellIndex];
                    var alignment                    = cellAlignment[cellIndex];
                    var separation                   = cellSeparation[cellIndex];
                    var nearestObstacleDistance      = cellObstacleDistance[cellIndex];
                    var nearestObstaclePositionIndex = cellObstaclePositionIndex[cellIndex];
                    var nearestTargetPositionIndex   = cellTargetPositionIndex[cellIndex];
                    var nearestObstaclePosition      = copyObstaclePositions[nearestObstaclePositionIndex];
                    var nearestTargetPosition        = copyTargetPositions[nearestTargetPositionIndex];

                    // Setting up the directions for the three main biocrowds influencing directions adjusted based
                    // on the predefined weights:
                    // 1) alignment - how much should it move in a direction similar to those around it?
                    // note: we use `alignment/neighborCount`, because we need the average alignment in this case; however
                    // alignment is currently the summation of all those of the boids within the cellIndex being considered.
                    var alignmentResult = settings.AlignmentWeight
                                          * math.normalizesafe((alignment / neighborCount) - forward);
                    // 2) separation - how close is it to other boids and are there too many or too few for comfort?
                    // note: here separation represents the summed possible center of the cell. We perform the multiplication
                    // so that both `currentPosition` and `separation` are weighted to represent the cell as a whole and not
                    // the current individual boid.
                    var separationResult = settings.SeparationWeight
                                           * math.normalizesafe((currentPosition * neighborCount) - separation);
                    // 3) target - is it still towards its destination?
                    var targetHeading = settings.TargetWeight
                                        * math.normalizesafe(nearestTargetPosition - currentPosition);

                    // creating the obstacle avoidant vector s.t. it's pointing towards the nearest obstacle
                    // but at the specified 'ObstacleAversionDistance'. If this distance is greater than the
                    // current distance to the obstacle, the direction becomes inverted. This simulates the
                    // idea that if `currentPosition` is too close to an obstacle, the weight of this pushes
                    // the current boid to escape in the fastest direction; however, if the obstacle isn't
                    // too close, the weighting denotes that the boid doesnt need to escape but will move
                    // slower if still moving in that direction (note: we end up not using this move-slower
                    // case, because of `targetForward`'s decision to not use obstacle avoidance if an obstacle
                    // isn't close enough).
                    var obstacleSteering     = currentPosition - nearestObstaclePosition;
                    var avoidObstacleHeading = (nearestObstaclePosition + math.normalizesafe(obstacleSteering)
                                                * settings.ObstacleAversionDistance) - currentPosition;

                    // the updated heading direction. If not needing to be avoidant (ie obstacle is not within
                    // predefined radius) then go with the usual defined heading that uses the amalgamation of
                    // the weighted alignment, separation, and target direction vectors.
                    var nearestObstacleDistanceFromRadius = nearestObstacleDistance - settings.ObstacleAversionDistance;
                    var normalHeading = math.normalizesafe(alignmentResult + separationResult + targetHeading);
                    var targetForward = math.select(normalHeading, avoidObstacleHeading, nearestObstacleDistanceFromRadius < 0);

                    // updates using the newly calculated heading direction
                    var nextHeading = math.normalizesafe(forward + deltaTime * (targetForward - forward));
                    localToWorld    = new LocalToWorld
                    {
                        Value = float4x4.TRS(
                            new float3(localToWorld.Position + (nextHeading * settings.MoveSpeed * deltaTime)),
                            quaternion.LookRotationSafe(nextHeading, math.up()),
                            new float3(1.0f, 1.0f, 1.0f))
                    };
                }).ScheduleParallel(mergeCellsJobHandle);

                // Dispose allocated containers with dispose jobs.
                Dependency = steerJobHandle;
                var disposeJobHandle = hashMap.Dispose(Dependency);
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellIndices.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellObstaclePositionIndex.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellTargetPositionIndex.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellCount.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellObstacleDistance.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellAlignment.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, cellSeparation.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, copyObstaclePositions.Dispose(Dependency));
                disposeJobHandle = JobHandle.CombineDependencies(disposeJobHandle, copyTargetPositions.Dispose(Dependency));
                Dependency       = disposeJobHandle;

                // We pass the job handle and add the dependency so that we keep the proper ordering between the jobs
                // as the looping iterates. For our purposes of execution, this ordering isn't necessary; however, without
                // the add dependency call here, the safety system will throw an error, because we're accessing multiple
                // pieces of boid data and it would think there could possibly be a race condition.

                m_BoidQuery.AddDependency(Dependency);
                m_BoidQuery.ResetFilter();
            }
            m_UniqueTypes.Clear();
        }
Example #13
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        if (!controller)
        {
            controller = BoidControllerECSJobsFast.Instance;
        }
        if (controller)
        {
            int boidCount = boidGroup.CalculateEntityCount();

            var cellIndices   = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var cellBoidCount = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var boidPositions = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var boidHeadings  = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var hashMap       = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);

            var positionsAndHeadingsCopyJob = new CopyPositionsAndHeadingsInBuffer {
                boidPositions = boidPositions,
                boidHeadings  = boidHeadings
            };
            JobHandle positionsAndHeadingsCopyJobHandle = positionsAndHeadingsCopyJob.Schedule(boidGroup, inputDeps);

            quaternion randomHashRotation = quaternion.Euler(
                UnityEngine.Random.Range(-360f, 360f),
                UnityEngine.Random.Range(-360f, 360f),
                UnityEngine.Random.Range(-360f, 360f)
                );
            float  offsetRange      = controller.boidPerceptionRadius / 2f;
            float3 randomHashOffset = new float3(
                UnityEngine.Random.Range(-offsetRange, offsetRange),
                UnityEngine.Random.Range(-offsetRange, offsetRange),
                UnityEngine.Random.Range(-offsetRange, offsetRange)
                );

            var hashPositionsJob = new HashPositionsToHashMap {
                hashMap            = hashMap.AsParallelWriter(),
                cellRotationVary   = randomHashRotation,
                positionOffsetVary = randomHashOffset,
                cellRadius         = controller.boidPerceptionRadius,
            };
            JobHandle hashPositionsJobHandle = hashPositionsJob.Schedule(boidGroup, inputDeps);

            // Proceed when these two jobs have been completed
            JobHandle copyAndHashJobHandle = JobHandle.CombineDependencies(
                positionsAndHeadingsCopyJobHandle,
                hashPositionsJobHandle
                );

            var mergeCellsJob = new MergeCellsJob {
                indicesOfCells = cellIndices,
                cellPositions  = boidPositions,
                cellHeadings   = boidHeadings,
                cellCount      = cellBoidCount,
            };
            JobHandle mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, copyAndHashJobHandle);

            var moveJob = new MoveBoids {
                deltaTime = Time.DeltaTime,
                boidSpeed = controller.boidSpeed,

                separationWeight = controller.separationWeight,
                alignmentWeight  = controller.alignmentWeight,
                cohesionWeight   = controller.cohesionWeight,

                cageSize        = controller.cageSize,
                cageAvoidDist   = controller.avoidWallsTurnDist,
                cageAvoidWeight = controller.avoidWallsWeight,

                cellSize            = controller.boidPerceptionRadius,
                cellIndices         = cellIndices,
                positionSumsOfCells = boidPositions,
                headingSumsOfCells  = boidHeadings,
                cellBoidCount       = cellBoidCount,
            };
            JobHandle moveJobHandle = moveJob.Schedule(boidGroup, mergeCellsJobHandle);
            moveJobHandle.Complete();
            hashMap.Dispose();

            inputDeps = moveJobHandle;
            boidGroup.AddDependency(inputDeps);

            return(inputDeps);
        }
        else
        {
            return(inputDeps);
        }
    }
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes);

            var obstacleCount = m_ObstacleQuery.CalculateEntityCount();
            var targetCount   = m_TargetQuery.CalculateEntityCount();

            // Cannot call [DeallocateOnJobCompletion] on Hashmaps yet, so doing own cleanup here
            // of the hashes created in the previous iteration.
            for (int i = 0; i < m_PrevFrameHashmaps.Count; ++i)
            {
                m_PrevFrameHashmaps[i].Dispose();
            }
            m_PrevFrameHashmaps.Clear();

            // Each variant of the Boid represents a different value of the SharedComponentData and is self-contained,
            // meaning Boids of the same variant only interact with one another. Thus, this loop processes each
            // variant type individually.
            for (int boidVariantIndex = 0; boidVariantIndex < m_UniqueTypes.Count; boidVariantIndex++)
            {
                var settings = m_UniqueTypes[boidVariantIndex];
                m_BoidQuery.SetFilter(settings);
                var boidCount = m_BoidQuery.CalculateEntityCount();

                if (boidCount == 0)
                {
                    // Early out. If the given variant includes no Boids, move on to the next loop.
                    // For example, variant 0 will always exit early bc it's it represents a default, uninitialized
                    // Boid struct, which does not appear in this sample.
                    continue;
                }

                // The following calculates spatial cells of neighboring Boids
                // note: working with a sparse grid and not a dense bounded grid so there
                // are no predefined borders of the space.

                var hashMap = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);

                var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellObstaclePositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellTargetPositionIndex   = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                var cellCount = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                var cellObstacleDistance = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellAlignment        = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellSeparation       = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                var copyTargetPositions   = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                // The following jobs all run in parallel because the same JobHandle is passed for their
                // input dependencies when the jobs are scheduled; thus, they can run in any order (or concurrently).
                // The concurrency is property of how they're scheduled, not of the job structs themselves.

                var initialCellAlignmentJob = new CopyHeadings
                {
                    headings = cellAlignment
                };
                var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(m_BoidQuery, inputDeps);

                var initialCellSeparationJob = new CopyPositions
                {
                    positions = cellSeparation
                };
                var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(m_BoidQuery, inputDeps);

                var copyTargetPositionsJob = new CopyPositions
                {
                    positions = copyTargetPositions
                };
                var copyTargetPositionsJobHandle = copyTargetPositionsJob.Schedule(m_TargetQuery, inputDeps);

                var copyObstaclePositionsJob = new CopyPositions
                {
                    positions = copyObstaclePositions
                };
                var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(m_ObstacleQuery, inputDeps);

                // Cannot call [DeallocateOnJobCompletion] on Hashmaps yet, so adding resolved hashes to the list
                // so that theyre usable in the upcoming cell jobs and also have a straight forward cleanup.
                m_PrevFrameHashmaps.Add(hashMap);

                // setting up the jobs for position and cell count

                var hashPositionsJob = new HashPositions
                {
                    hashMap    = hashMap.AsParallelWriter(),
                    cellRadius = settings.CellRadius
                };
                var hashPositionsJobHandle = hashPositionsJob.Schedule(m_BoidQuery, inputDeps);

                var initialCellCountJob = new MemsetNativeArray <int>
                {
                    Source = cellCount,
                    Value  = 1
                };
                var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDeps);

                var initialCellBarrierJobHandle        = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle);
                var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle);
                var mergeCellsBarrierJobHandle         = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle);

                var mergeCellsJob = new MergeCells
                {
                    cellIndices               = cellIndices,
                    cellAlignment             = cellAlignment,
                    cellSeparation            = cellSeparation,
                    cellObstacleDistance      = cellObstacleDistance,
                    cellObstaclePositionIndex = cellObstaclePositionIndex,
                    cellTargetPositionIndex   = cellTargetPositionIndex,
                    cellCount         = cellCount,
                    targetPositions   = copyTargetPositions,
                    obstaclePositions = copyObstaclePositions
                };
                var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle);

                var steerJob = new Steer
                {
                    cellIndices               = cellIndices,
                    settings                  = settings,
                    cellAlignment             = cellAlignment,
                    cellSeparation            = cellSeparation,
                    cellObstacleDistance      = cellObstacleDistance,
                    cellObstaclePositionIndex = cellObstaclePositionIndex,
                    cellTargetPositionIndex   = cellTargetPositionIndex,
                    cellCount                 = cellCount,
                    targetPositions           = copyTargetPositions,
                    obstaclePositions         = copyObstaclePositions,
                    dt = Time.deltaTime,
                };
                var steerJobHandle = steerJob.Schedule(m_BoidQuery, mergeCellsJobHandle);

                inputDeps = steerJobHandle;
                m_BoidQuery.AddDependency(inputDeps);
            }
            m_UniqueTypes.Clear();

            return(inputDeps);
        }
Example #15
0
        protected override void OnUpdate()
        {
            if (Camera.main == null)
            {
                return;
            }

            var lineList = m_LineList;

            Camera.main.RemoveCommandBuffers(CameraEvent.AfterEverything);
            Camera.main.AddCommandBuffer(CameraEvent.AfterEverything, m_CommandBuffer);
            if (lineList.Length > MaxLines)
            {
                Debug.LogWarning("Trying to render " + lineList.Length + " but limit is " + MaxLines);
                lineList.ResizeUninitialized(MaxLines);
            }

            var curOffset = m_RenderOffset[0];

            NativeArray <Line> lines = lineList;

            m_Material.SetFloat("offsetX", curOffset.x);
            m_Material.SetFloat("offsetY", curOffset.y);
            m_Material.SetFloat("screenWidth", Screen.width);
            m_Material.SetFloat("screenHeight", Screen.height);
            m_Material.SetBuffer("lines", m_ComputeBuffer);
            m_ComputeBuffer.SetData(lines);
            m_CommandBuffer.Clear();
            m_CommandBuffer.DrawProcedural(Matrix4x4.identity, m_Material, -1, MeshTopology.Triangles,
                                           lineList.Length * 6);
            lineList.Clear();

            JobHandle levelHandle;
            var       list         = m_LineList;
            var       queue        = m_LineQueue;
            var       renderOffset = m_RenderOffset;
            var       renderSize   = new float2(Screen.width, Screen.height);
            var       deltaTime    = Time.DeltaTime;
            var       level        = m_LevelGroup.ToComponentDataArrayAsync <LevelComponent>(Allocator.TempJob, out levelHandle);

            var copyToListJob = Entities.WithReadOnly(level).WithDeallocateOnJobCompletion(level).ForEach(
                (ref LineRendererComponentData lineData) =>
            {
                if (level.Length > 0)
                {
                    list.Add(new Line(new float2(0, 0), new float2(level[0].width, 0), new float4(1, 0, 0, 1), 5));
                    list.Add(new Line(new float2(0, 0), new float2(0, level[0].height), new float4(1, 0, 0, 1), 5));
                    list.Add(new Line(new float2(0, level[0].height), new float2(level[0].width, level[0].height),
                                      new float4(1, 0, 0, 1), 5));
                    list.Add(new Line(new float2(level[0].width, 0), new float2(level[0].width, level[0].height),
                                      new float4(1, 0, 0, 1), 5));
                }

                var offset        = renderOffset[0];
                var target        = lineData.targetOffset;
                renderOffset[1]   = target;
                float maxPxPerSec = 500;
                if (math.any(offset != target))
                {
                    if (lineData.teleport != 0)
                    {
                        offset = target;
                    }
                    else
                    {
                        float2 delta   = (target - offset);
                        float deltaLen = math.length(delta);
                        float maxDiff  = maxPxPerSec * deltaTime;
                        if (deltaLen > maxDiff || deltaLen < -maxDiff)
                        {
                            delta *= maxDiff / deltaLen;
                        }
                        offset += delta;
                    }

                    renderOffset[0] = offset;
                }

                Line line;
                while (queue.TryDequeue(out line))
                {
                    if ((line.start.x < offset.x - line.width && line.end.x < offset.x - line.width) ||
                        (line.start.x > offset.x + renderSize.x + line.width &&
                         line.end.x > offset.x + renderSize.x + line.width) ||
                        (line.start.y < offset.y - line.width && line.end.y < offset.y - line.width) ||
                        (line.start.y > offset.y + renderSize.y + line.width &&
                         line.end.y > offset.y + renderSize.y + line.width))
                    {
                        continue;
                    }
                    list.Add(line);
                }
            }).Schedule(JobHandle.CombineDependencies(Dependency, levelHandle));

            Dependency = copyToListJob;
            m_LineGroup.AddDependency(Dependency);
        }
Example #16
0
    protected override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        Settings settings;

        settings.CellRadius        = 16;
        settings.SeparationWeight  = 1;
        settings.AlignmentWeight   = 1;
        settings.TargetWeight      = 2;
        settings.MaxTargetDistance = 10000;
        //settings.ObstacleAversionDistance = 35;
        settings.MoveSpeed  = 25;
        settings.boidRadius = 0.5f;

        EntityManager.GetAllUniqueSharedComponentData(uniqueFactions);

        int healthCount = healthQuery.CalculateEntityCount();

        for (int i = 0; i < prevFrameHashmaps.Count; i++)
        {
            prevFrameHashmaps[i].Dispose();
        }
        prevFrameHashmaps.Clear();

        for (int index = 0; index < uniqueFactions.Count; index++)
        {
            boidQuery.SetFilter(uniqueFactions[index]);

            int boidCount = boidQuery.CalculateEntityCount();

            if (boidCount == 0)
            {
                continue;
            }

            var cellIndices          = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var hashMap              = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);
            var cellObstacleDistance = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var cellCount            = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var killTrigger          = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var cellAlignment = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                         NativeArrayOptions.UninitializedMemory);
            var cellSeparation = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                          NativeArrayOptions.UninitializedMemory);
            var boidsData = new NativeArray <Boid>(boidCount, Allocator.TempJob,
                                                   NativeArrayOptions.UninitializedMemory);
            var cellTargetPositions = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                               NativeArrayOptions.UninitializedMemory);
            var cellObstaclePositions = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                                 NativeArrayOptions.UninitializedMemory);
            var bulletSpawns = new NativeArray <BulletSpawn>(boidCount, Allocator.TempJob,
                                                             NativeArrayOptions.ClearMemory);

            var damageDict = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);

            var initialCellAlignmentJob = new CopyHeadings {
                headings = cellAlignment
            };
            var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(boidQuery, inputDependencies);

            var initialCellSeparationJob = new CopyPositions {
                positions = cellSeparation
            };
            var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(boidQuery, inputDependencies);

            var initialBoidData = new CopyBoids {
                boids = boidsData
            };
            var initialBoidDataJobHandle = initialBoidData.Schedule(boidQuery, inputDependencies);

            // Cannot call [DeallocateOnJobCompletion] on Hashmaps yet
            prevFrameHashmaps.Add(hashMap);

            var hashPositionsJob = new HashPositions {
                hashMap    = hashMap.AsParallelWriter(),
                cellRadius = settings.CellRadius
            };
            var hashPositionsJobHandle = hashPositionsJob.Schedule(boidQuery, inputDependencies);

            var initialCellCountJob = new MemsetNativeArray <int> {
                Source = cellCount,
                Value  = 1
            };
            var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDependencies);

            var killTriggerJob = new MemsetNativeArray <int> {
                Source = killTrigger,
                Value  = 0
            };
            var killTriggerJobHandle = killTriggerJob.Schedule(boidCount, 64, inputDependencies);

            var initialCellBarrierJobHandle = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle);
            var initialBoidBarrierJobHandle = JobHandle.CombineDependencies(initialBoidDataJobHandle, killTriggerJobHandle);
            var mergeCellsBarrierJobHandle  = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, initialBoidBarrierJobHandle);

            ref PhysicsWorld physicsWorld = ref Unity.Entities.World.Active.GetExistingSystem <BuildPhysicsWorld>().PhysicsWorld;

            var commandBuffer = m_Barrier.CreateCommandBuffer().ToConcurrent();
            prevFrameHashmaps.Add(damageDict);

            var mergeCellsJob = new MergeCells {
                cellIndices           = cellIndices,
                cellObstaclePositions = cellObstaclePositions,
                cellTargetPositions   = cellTargetPositions,
                cellAlignment         = cellAlignment,
                cellSeparation        = cellSeparation,
                cellObstacleDistance  = cellObstacleDistance,
                cellCount             = cellCount,
                boidsData             = boidsData,
                killTrigger           = killTrigger,
                physicsWorld          = physicsWorld,
                damageDict            = damageDict.AsParallelWriter(),
                bulletSpawns          = bulletSpawns,
                commandBuffer         = commandBuffer,
                bulletPrefab          = BulletPrefabAuthoring.Prefab,
                //enemyEntityLook = Setup.enemyEntityLook,
                groupIndex = math.select(4u, 8u, uniqueFactions[index].Value == 0),
                time       = Time.time,
                settings   = settings,
            };
            var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle);

            m_Barrier.AddJobHandleForProducer(mergeCellsJobHandle);

            var applyBulletSpawnDataJob = new ApplyBulletSpawnData {
                bulletSpawns  = bulletSpawns,
                destroyAtTime = Time.time + 5,
                commandBuffer = commandBuffer,
                bulletPrefab  = BulletPrefabAuthoring.Prefab
            };
            var applyBulletSpawnDataJobHandle = applyBulletSpawnDataJob.Schedule(boidCount, 64, mergeCellsJobHandle);

            m_Barrier.AddJobHandleForProducer(applyBulletSpawnDataJobHandle);

            var updateBoidData = new UpdateBoidData {
                boidsData = boidsData
            };
            var updateBoidDataJobHandle = updateBoidData.Schedule(boidQuery, applyBulletSpawnDataJobHandle);

            var steerJob = new Steer {
                cellIndices          = cellIndices,
                settings             = settings,
                cellAlignment        = cellAlignment,
                cellSeparation       = cellSeparation,
                cellObstacleDistance = cellObstacleDistance,
                cellCount            = cellCount,
                targetPositions      = cellTargetPositions,
                obstaclePositions    = cellObstaclePositions,
                boidsData            = boidsData,
                dt = Time.deltaTime,
            };
            var steerJobHandle = steerJob.Schedule(boidQuery, updateBoidDataJobHandle);

            var killJob = new Kill {
                killTrigger   = killTrigger,
                commandBuffer = commandBuffer,
            };
            var killJobHandle = killJob.Schedule(boidQuery, steerJobHandle);

            m_Barrier.AddJobHandleForProducer(killJobHandle);

            var applyDamageJob = new ApplyDamage {
                damageDict = damageDict
            };
            var applyDamageJobHandle = applyDamageJob.Schedule(healthQuery, mergeCellsJobHandle);

            inputDependencies = JobHandle.CombineDependencies(killJobHandle, applyDamageJobHandle, applyBulletSpawnDataJobHandle);
            boidQuery.AddDependency(inputDependencies);
        }
Example #17
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            EntityCommandBuffer.Concurrent commandBuffer = endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
            BoundingVolume playerBounds = GetComponentDataFromEntity <BoundingVolume>(true)[GameHandler.playerEntity];
            HealthFloat    playerHealth = GetComponentDataFromEntity <HealthFloat>(true)[GameHandler.playerEntity];
            Player         player       = GetComponentDataFromEntity <Player>(true)[GameHandler.playerEntity];

            // job for collision between player and enemies
            Entity    playerEntity = GameHandler.playerEntity;
            JobHandle jobHandle    = Entities
                                     .WithNone <Bullet>()
                                     .ForEach((Entity entity, int entityInQueryIndex, ref BoundingVolume vol, ref HealthModifier healthMod) =>
            {
                if (vol.volume.Intersects(playerBounds.volume))
                {
                    // there was a collision, modify the player's health
                    Utils.ModifyHealth(ref playerHealth, healthMod.value);
                    commandBuffer.SetComponent <HealthFloat>(entityInQueryIndex, playerEntity, playerHealth);

                    // get rid of the damager
                    commandBuffer.DestroyEntity(entityInQueryIndex, entity);
                }
            }).Schedule(inputDeps);

            EntityQuery bulletQuery = EntityManager.CreateEntityQuery(typeof(Bullet), ComponentType.ReadOnly <BoundingVolume>(), ComponentType.ReadOnly <HealthModifier>());

            bulletQuery.AddDependency(jobHandle);

            NativeArray <BoundingVolume> bulletColliders  = bulletQuery.ToComponentDataArray <BoundingVolume>(Allocator.TempJob);
            NativeArray <HealthModifier> bulletHealthMods = bulletQuery.ToComponentDataArray <HealthModifier>(Allocator.TempJob);
            NativeArray <Bullet>         bulletInfos      = bulletQuery.ToComponentDataArray <Bullet>(Allocator.TempJob);
            NativeArray <Entity>         bullets          = bulletQuery.ToEntityArray(Allocator.TempJob);

            // job for checking collisions between enemies and bullets
            jobHandle = Entities
                        .WithDeallocateOnJobCompletion(bulletColliders)
                        .WithDeallocateOnJobCompletion(bulletHealthMods)
                        .WithDeallocateOnJobCompletion(bulletInfos)
                        .WithDeallocateOnJobCompletion(bullets)
                        .WithReadOnly(bulletColliders)
                        .WithReadOnly(bulletHealthMods)
                        .WithReadOnly(bulletInfos)
                        .WithReadOnly(bullets)
                        .WithNone <Player>()
                        .WithAll <Enemy>()
                        .ForEach((Entity entity, int entityInQueryIndex, ref BoundingVolume damageableCollider, ref HealthFloat damageableHealth) =>
            {
                for (int i = 0; i < bulletColliders.Length; i++)
                {
                    // bullet isn't active, leave
                    if (!bulletInfos[i].isActive)
                    {
                        continue;
                    }

                    if (damageableCollider.volume.Intersects(bulletColliders[i].volume))
                    {
                        // bullet hit a damageable, reduce it's health
                        Utils.ModifyHealth(ref damageableHealth, bulletHealthMods[i].value);

                        // deactivate the bullet
                        Bullet b   = bulletInfos[i];
                        b.isActive = false;
                        b.age      = 0;
                        commandBuffer.SetComponent <Bullet>(entityInQueryIndex, bullets[i], b);
                    }
                }
            }).Schedule(jobHandle);
            jobHandle.Complete();

            jobHandle = Entities
                        .ForEach((Entity entity, int entityInQueryIndex, ref Enemy enemy, ref HealthFloat health) =>
            {
                if (health.curr <= 0)
                {
                    // destroy any entity who's health has dropped below 0
                    commandBuffer.DestroyEntity(entityInQueryIndex, entity);
                    player.score += enemy.points;
                    commandBuffer.SetComponent <Player>(entityInQueryIndex, playerEntity, player);
                }
            }).Schedule(jobHandle);
            jobHandle.Complete();

            endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(jobHandle);
            return(jobHandle);
        }
Example #18
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes);

        // var a = EntityManager.GetSharedComponentOrderVersion<MoveActions> (m_UniqueTypes[0]);
        // var b = EntityManager.GetSharedComponentOrderVersion<MoveActions> (m_UniqueTypes[2]);
        foreach (var uniqueType in m_UniqueTypes)
        {
            Debug.Log(uniqueType + " ID :" + EntityManager.GetSharedComponentOrderVersion <MoveActions>(uniqueType));
        }
        Debug.Log("unique types:" + m_UniqueTypes.Count);
        //we start at one because the first one is simply the uninitialised version
        if (m_UniqueTypes.Count > 1)
        {
            for (int i = 1; i < m_UniqueTypes.Count; i++)
            {
                //  Debug.Log ("distance: " + ArrayToString( m_UniqueTypes[i].distances));
                //  Debug.Log ("rotations: " + ArrayToString(m_UniqueTypes[i].rotations));
                m_MoveActionsGroup.SetFilter(m_UniqueTypes[i]);
                int cacheIndex = i - 1;
                NativeArray <float> moveActionsDistances = new NativeArray <float>(1, Allocator.TempJob);
                NativeArray <float> moveActionsRotations = new NativeArray <float>(1, Allocator.TempJob);

                /*     if (m_UniqueTypes[i].distances.Length != m_UniqueTypes[i].rotations.Length) { Debug.LogError ("there must be a rotation for each direction given"); }
                 * if (m_UniqueTypes[i].distances.Length > 0) { moveActionsDistances = new NativeArray<float> (m_UniqueTypes[i].distances, Allocator.TempJob); }
                 * else { Debug.LogError ("movactions distance has no data, without any actions this will fail."); }
                 * if (m_UniqueTypes[i].rotations.Length > 0) { moveActionsRotations = new NativeArray<float> (m_UniqueTypes[i].rotations, Allocator.TempJob); }
                 * else { Debug.LogError ("movactions rotations has no data, without any actions this will fail."); }
                 */
                //  var tran else { Debug.LogError("movactions has no data, without any actiosn this will fail.") }slation = m_MoveActionsGroup.ToComponentDataArray<Translation> (Allocator.TempJob, out JobHandle getTranslationJobHandle);
                //    var combinedHandles = JobHandle.CombineDependencies (inputDeps, getTranslationJobHandle);
                var moveActions = m_UniqueTypes[i];

                //Essentially what this is doing is checking each time the job runs if the
                var nextActions = new PreviousActions
                {
                    MoveActionsDistances = moveActionsDistances,
                    MoveActionsRotations = moveActionsRotations
                };
                if (cacheIndex > (m_previousActions.Count - 1))
                {
                    m_previousActions.Add(nextActions);
                }
                else
                {
                    m_previousActions[cacheIndex].MoveActionsDistances.Dispose();
                    m_previousActions[cacheIndex].MoveActionsRotations.Dispose();
                }
                m_previousActions[cacheIndex] = nextActions;

                ExecuteActions executeActionsJob = new ExecuteActions
                {
                    deltaTime = Time.deltaTime,
                    // storableEntityData = m_storeableEntityData,
                    // postion = translation,
                    //moveActions = m_UniqueTypes[i],
                    rotations     = moveActionsRotations,
                    distances     = moveActionsDistances,
                    CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer()
                };

                JobHandle executeActionsJobHandle = executeActionsJob.Schedule(this, inputDeps);
                inputDeps = executeActionsJobHandle;

                m_EntityCommandBufferSystem.AddJobHandleForProducer(inputDeps);
                m_MoveActionsGroup.AddDependency(inputDeps);
                //moveActionsRotations.Dispose();
                // moveActionsDistances.Dispose();
            }
        }
        m_UniqueTypes.Clear();

        return(inputDeps);
    }
Example #19
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            var settings     = ECSController.FlockParams;
            var gameSettings = GlobalSettings.Instance;

            EntityManager.GetAllUniqueSharedComponentData(UniqueTypes);

            int targetsCount   = BoidTargetsGroup.CalculateLength();
            int obstaclesCount = BoidObstaclesGroup.CalculateLength();

            UIControl.Instance.NrOfObstacles = obstaclesCount;

            // Ignore typeIndex 0, can't use the default for anything meaningful.
            for (int typeIndex = 1; typeIndex < UniqueTypes.Count; typeIndex++)
            {
                Boid boid = UniqueTypes[typeIndex];
                BoidGroup.SetFilter(boid);

                var boidCount = BoidGroup.CalculateLength();
                UIControl.Instance.NrOfBoidsAlive = boidCount;

                var cacheIndex = typeIndex - 1;
                // containers that store all the data.
                var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var hashMap     = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);
                var cellCount   = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                var cellAlignment = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                             NativeArrayOptions.UninitializedMemory);
                var cellPositions = new NativeArray <float3>(boidCount, Allocator.TempJob,
                                                             NativeArrayOptions.UninitializedMemory);

                var targetsPositions = new NativeArray <float3>(targetsCount, Allocator.TempJob,
                                                                NativeArrayOptions.UninitializedMemory);
                var closestTargetIndices = new NativeArray <int>(boidCount, Allocator.TempJob,
                                                                 NativeArrayOptions.UninitializedMemory);

                var obstaclesPositions = new NativeArray <float3>(obstaclesCount, Allocator.TempJob,
                                                                  NativeArrayOptions.UninitializedMemory);
                var closestObstacleIndices = new NativeArray <int>(boidCount, Allocator.TempJob,
                                                                   NativeArrayOptions.UninitializedMemory);
                var closestObstacleSqDistances = new NativeArray <float>(boidCount, Allocator.TempJob,
                                                                         NativeArrayOptions.UninitializedMemory);

                float3 sumOfAllBoidsPositions = float3.zero;

                // copy values to buffers.
                var initialCellAlignmentJob = new CopyHeadingsInBuffer {
                    headingsResult = cellAlignment
                };
                var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(BoidGroup, inputDeps);

                var initialCopyPositionJob = new CopyPositionsInBuffer {
                    positionsResult = cellPositions
                };
                var initialCopyPositionJobHandle = initialCopyPositionJob.Schedule(BoidGroup, inputDeps);

                var sumPositionsJob = new SumPositions {
                    positionsSum = sumOfAllBoidsPositions
                };
                var sumPositionsJobHandle = sumPositionsJob.Schedule(BoidGroup, inputDeps);

                // copy targets positions
                var copyPositionsOfTargetsJob = new CopyPositionsInBuffer {
                    positionsResult = targetsPositions
                };
                var copyPositionsOfTargetsJobHandle = copyPositionsOfTargetsJob.Schedule(BoidTargetsGroup, inputDeps);

                // copy obstacles positions
                var copyPositionsOfObstaclesJob = new CopyPositionsInBuffer {
                    positionsResult = obstaclesPositions
                };
                var copyPositionsOfObstaclesJobHandle = copyPositionsOfObstaclesJob.Schedule(BoidObstaclesGroup, inputDeps);

                var newCellData = new CellsData {
                    indicesOfCells = cellIndices,
                    hashMapBlockIndexWithBoidsIndex = hashMap,
                    sumOfDirectionsOnCells          = cellAlignment,
                    sumOfPositionsOnCells           = cellPositions,
                    nrOfBoidsOnCells           = cellCount,
                    targetsPositions           = targetsPositions,
                    closestTargetIndices       = closestTargetIndices,
                    closestObstacleIndices     = closestObstacleIndices,
                    closestObstacleSqDistances = closestObstacleSqDistances,
                    obstaclesPositions         = obstaclesPositions,
                };

                if (cacheIndex > (_CellsData.Count - 1))
                {
                    _CellsData.Add(newCellData);
                }
                else
                {
                    DisposeCellData(_CellsData[cacheIndex]);
                }
                _CellsData[cacheIndex] = newCellData;

                // hash the entity position
                var hashPositionsJob = new HashPositionsToHashMap {
                    hashMap            = hashMap.ToConcurrent(),
                    cellRadius         = ECSController.Instance.CellSizeVaried,
                    positionOffsetVary = ECSController.Instance.PositionNeighbourCubeOffset
                };
                var hashPositionsJobHandle = hashPositionsJob.Schedule(BoidGroup, inputDeps);

                // set all cell count to 1.
                var initialCellCountJob = new MemsetNativeArray <int> {
                    Source = cellCount,
                    Value  = 1
                };
                var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDeps);

                // bariers. from now on we need to use the created buffers.
                // and we need to know that they are finished.
                var initialCellBarrierJobHandle = JobHandle.CombineDependencies(
                    initialCellAlignmentJobHandle, initialCopyPositionJobHandle, initialCellCountJobHandle);
                var mergeCellsBarrierJobHandle = JobHandle.CombineDependencies(
                    hashPositionsJobHandle, initialCellBarrierJobHandle, sumPositionsJobHandle);
                var targetsJobHandle = JobHandle.CombineDependencies(mergeCellsBarrierJobHandle,
                                                                     copyPositionsOfTargetsJobHandle, copyPositionsOfObstaclesJobHandle);

                var mergeCellsJob = new MergeCellsJob {
                    indicesOfCells                   = cellIndices,
                    cellAlignment                    = cellAlignment,
                    cellPositions                    = cellPositions,
                    cellCount                        = cellCount,
                    targetsPositions                 = targetsPositions,
                    closestTargetIndexToCells        = closestTargetIndices,
                    closestObstacleSqDistanceToCells = closestObstacleSqDistances,
                    closestObstacleIndexToCells      = closestObstacleIndices,
                    obstaclesPositions               = obstaclesPositions
                };
                // job now depends on last barrier.
                var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, targetsJobHandle);
                EntityCommandBuffer.Concurrent commandBuffer        = barrierCommand.CreateCommandBuffer().ToConcurrent();
                NativeQueue <float3>           killedPositionsQueue = new NativeQueue <float3>(Allocator.TempJob);

                var steerJob = new MoveBoids {
                    cellIndices          = newCellData.indicesOfCells,
                    alignmentWeight      = gameSettings.AlignmentWeight,
                    separationWeight     = gameSettings.SeparationWeight,
                    cohesionWeight       = gameSettings.CohesionWeight,
                    cellSize             = ECSController.Instance.CellSizeVaried,
                    sphereBoundarySize   = gameSettings.SphereBoundarySize,
                    sphereBoundaryWeight = gameSettings.BoundaryWeight,
                    moveSpeed            = gameSettings.MoveSpeed,
                    cellAlignment        = cellAlignment,
                    cellPositions        = cellPositions,
                    cellCount            = cellCount,
                    dt = Time.deltaTime,
                    walkToFlockCenterWeight = gameSettings.WalkToFlockCenterWeight,
                    sumOfAllPositions       = sumOfAllBoidsPositions,
                    nrOfTotalBoids          = boidCount,
                    maintainYWeight         = gameSettings.maintainYWeight,
                    yLength                         = gameSettings.yLength,
                    perlinNoiseScale                = settings.perlinNoiseScale,
                    targetsPositions                = targetsPositions,
                    cellClosestTargetsIndices       = closestTargetIndices,
                    goToTargetsWeight               = gameSettings.goToTargetsWeight,
                    obstaclesPositions              = obstaclesPositions,
                    cellClosestObstaclesIndices     = closestObstacleIndices,
                    cellClosestObstaclesSqDistances = closestObstacleSqDistances,
                    startAvoidingObstacleAtDistance = gameSettings.avoidDistanceObstacles,
                    avoidObstaclesWeight            = gameSettings.avoidObstaclesWeight,
                    terrainY                        = ECSController.TerrainY,
                    distanceToAvoidTerrain          = settings.distanceToAvoidTerrain,
                    avoidTerrainWeight              = gameSettings.avoidTerrainWeight,
                    avoidXZwhileHeightBiggerThan    = settings.avoidXZwhileHeightBiggerThan,
                    avoidXZwhileHeightBiggerFade    = settings.avoidXZwhileHeightBiggerFade,
                    obstacleKillRadius              = settings.obstacleKillRadius,
                    commandBuffer                   = commandBuffer,
                    diedPositions                   = killedPositionsQueue.ToConcurrent(),
                };
                // job depends on merge cells job
                var steerJobHandle = steerJob.Schedule(BoidGroup, mergeCellsJobHandle);

                barrierCommand.AddJobHandleForProducer(steerJobHandle);
                steerJobHandle.Complete();

                if (killedPositionsQueue.TryDequeue(out float3 pos))
                {
                    GameController.Instance.KilledBoidAt(pos);
                }

                killedPositionsQueue.Dispose();
                inputDeps = steerJobHandle;
                BoidGroup.AddDependency(inputDeps);
            }
            UniqueTypes.Clear();

            return(inputDeps);
        }