Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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);
        }
    }