public static JobHandle GetChangedChunks <T>( this EntityQuery query, ComponentSystemBase system, Allocator allocator, ref NativeQueue <VTuple <int, int> > .ParallelWriter changedEntitySlices, JobHandle inputDeps, bool changeAll = false) where T : struct, IComponentData { var chunks = query.CreateArchetypeChunkArrayAsync(allocator, out var createChunksHandle); inputDeps = JobHandle.CombineDependencies(inputDeps, createChunksHandle); var indicesState = new NativeArray <int>(chunks.Length, Allocator.TempJob); inputDeps = new MemsetNativeArray <int> { Source = indicesState, Value = -1 }.Schedule(indicesState.Length, 64, inputDeps); inputDeps = new GatherChunkChanged <T> { ChunkType = system.GetArchetypeChunkComponentType <T>(true), ChangedIndices = indicesState, LastSystemVersion = system.LastSystemVersion, ForceChange = changeAll }.Schedule(query, inputDeps); inputDeps = new ExtractChangedSlicesFromChunks { Source = indicesState, Chunks = chunks, Slices = changedEntitySlices }.Schedule(indicesState.Length, 64, inputDeps); inputDeps = indicesState.Dispose(inputDeps); return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (m_BoardQuery.CalculateEntityCount() <= 0) { return(inputDeps); } var boardEntity = m_BoardQuery.GetSingletonEntity(); var board = m_BoardQuery.GetSingleton <LbBoard>(); var bufferLookup = GetBufferFromEntity <LbCatMap>(); var buffer = bufferLookup[boardEntity]; var bufferArray = buffer.AsNativeArray(); var handle = new MemsetNativeArray <LbCatMap>() { Source = bufferArray, Value = new LbCatMap() }.Schedule(bufferArray.Length, 32, inputDeps); handle = new CatMapJob { Size = board.SizeY, Buffer = bufferArray, Translations = m_CatQuery.ToComponentDataArray <Translation>(Allocator.TempJob) }.Schedule(handle); handle = new CollisionJob { Size = board.SizeY, CatLocationBuffer = bufferArray, Queue = m_Queue.AsParallelWriter(), }.Schedule(this, handle); handle = new CollisionCleanJob { Queue = m_Queue, CommandBuffer = m_Barrier.CreateCommandBuffer(), }.Schedule(handle); m_Barrier.AddJobHandleForProducer(handle); return(handle); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var board = m_BoardQuery.GetSingleton <LbBoard>(); var entitiesSpawners = m_ArrowSpawerQuery.ToEntityArray(Allocator.TempJob); var entitiesArrows = m_ArrowsQuery.ToEntityArray(Allocator.TempJob); var arrowSpawners = m_ArrowSpawerQuery.ToComponentDataArray <LbArrowSpawner>(Allocator.TempJob); var boardEntity = m_BoardQuery.GetSingletonEntity(); var arrowsQuery = m_ArrowsQuery.ToComponentDataArray <LbArrow>(Allocator.TempJob); var bufferLookup = GetBufferFromEntity <LbArrowDirectionMap>(); var buffer = bufferLookup[boardEntity]; var bufferArray = buffer.AsNativeArray(); var commandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer(); var handle = new MemsetNativeArray <LbArrowDirectionMap>() { Source = bufferArray, Value = new LbArrowDirectionMap() }.Schedule(bufferArray.Length, bufferArray.Length, inputDeps); handle = new SpawnArrow { Entities = entitiesSpawners, ArrowSpawners = arrowSpawners, CommandBuffer = commandBuffer }.Schedule(handle); handle = new WriteArroMap { Size = board.SizeY, Entities = entitiesArrows, LbArrows = arrowsQuery, ArrowDirectionMap = bufferArray, }.Schedule(handle); m_EntityCommandBufferSystem.AddJobHandleForProducer(handle); return(handle); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var boardEntity = m_Query.GetSingletonEntity(); var board = m_Query.GetSingleton <LbBoard>(); var bufferLookup = GetBufferFromEntity <LbCatMap>(); var buffer = bufferLookup[boardEntity]; var bufferArray = buffer.AsNativeArray(); var cleanJobHandle = new MemsetNativeArray <LbCatMap>() { Source = bufferArray, Value = new LbCatMap() }.Schedule(bufferArray.Length, 32, inputDeps); var jobHandle = new CatMapJob { Size = board.SizeY, Buffer = bufferArray, Translations = m_CatQuery.ToComponentDataArray <Translation>(Allocator.TempJob) }.Schedule(cleanJobHandle); return(jobHandle); }
private void InitJobData() { float deltaTime = 0f; #region JobDataSetup // //Init all job data here. Declare roughly inline. Optional brackets for things that can be parallel // #region ResetBeginningOfSimFrame _jobDataResetBlobAccelerations = new MemsetNativeArray <float2> { Source = _blobAccelerations, Value = float2.zero }; _jobDataResetCursorAccelerations = new MemsetNativeArray <float2> { Source = _cursorAccelerations, Value = float2.zero }; _jobDataResetGooGroups = new MemsetNativeArray <int> { Source = _blobGroupIDs, Value = -1 }; // _jobDataCopyBlobRadii = new MemsetNativeArray<float> {Source = _blobRadii, Value = GooPhysics.MaxSpringDistance}; _jobDataCopyBlobInfoToFloat3 = new JobCopyBlobInfoToFloat3 { BlobPos = _blobPositions, BlobTeams = _blobTeamIDs, BlobPosFloat3 = _blobPositionsV3 }; _jobBuildKnnTree = new KnnRebuildJob(_knnContainer); // Initialize all the range query results _blobKNNNearestNeighbourQueryResults = new NativeArray <RangeQueryResult>(_blobPositions.Length, Allocator.Persistent); _uniqueBlobEdges = new NativeMultiHashMap <int, int>(_blobPositions.Length * 40, Allocator.Persistent); _uniqueBlobEdgesHashSet = new NativeHashSet <long>(_blobPositions.Length * 40, Allocator.Persistent); // Each range query result object needs to declare upfront what the maximum number of points in range is for (int i = 0; i < _blobKNNNearestNeighbourQueryResults.Length; ++i) { _blobKNNNearestNeighbourQueryResults[i] = new RangeQueryResult(GooPhysics.MaxNearestNeighbours, Allocator.Persistent); } _jobDataQueryNearestNeighboursKNN = new QueryRangesBatchJob { m_container = _knnContainer, m_queryPositions = _blobPositionsV3, m_SearchRadius = GooPhysics.MaxSpringDistance, Results = _blobKNNNearestNeighbourQueryResults }; #endregion //ResetBeginningOfSimFrame #region Updates //build edges with existing positions _jobDataFloodFillGroupIDsKnn = new JobFloodFillIDsKnn() { BlobNearestNeighbours = _blobKNNNearestNeighbourQueryResults, GroupIDs = _blobGroupIDs, FloodQueue = _floodQueue, NumGroups = _numGroups //for safety.don't want divide by zero }; _jobDataFloodFillGroupIDsMultiHashMap = new JobFloodFillIDsUniqueEdges() { Springs = _uniqueBlobEdges, GroupIDs = _blobGroupIDs, FloodQueue = _floodQueue, NumGroups = _numGroups //for safety.don't want divide by zero }; _jobDataSpringForcesUsingKnn = new JobSpringForceUsingKNNResults { AccelerationAccumulator = _blobAccelerations, BlobNearestNeighbours = _blobKNNNearestNeighbourQueryResults, MaxEdgeDistanceRaw = GooPhysics.MaxSpringDistance * 2.0f, SpringConstant = GooPhysics.SpringForce, DampeningConstant = GooPhysics.DampeningConstant, Positions = _blobPositions, Velocity = _blobVelocities, }; _jobCompileDataUniqueEdges = new JobCompileUniqueEdges { BlobNearestNeighbours = _blobKNNNearestNeighbourQueryResults, Edges = _uniqueBlobEdges.AsParallelWriter(), UniqueEdges = _uniqueBlobEdgesHashSet.AsParallelWriter() }; _jobDataSpringForcesUniqueEdges = new JobUniqueSpringForce { AccelerationAccumulator = _blobAccelerations, Springs = _uniqueBlobEdges, MaxEdgeDistanceRaw = GooPhysics.MaxSpringDistance * 2.0f, SpringConstant = GooPhysics.SpringForce, DampeningConstant = GooPhysics.DampeningConstant, Positions = _blobPositions, Velocity = _blobVelocities, }; _jobDataFluidInfluence = new JobVelocityInfluenceFalloff { BlobPositions = _blobPositions, BlobVelocities = _blobVelocities, BlobNearestNeighbours = _blobKNNNearestNeighbourQueryResults, InfluenceRadius = _blobRadii, InfluenceModulator = GooPhysics.FluidInfluenceModulator, BlobAccelAccumulator = _blobAccelerations }; //update cursor accel based on inputs //todo: could be CopyTo? //_cursorInputDeltas.CopyTo(_cursorAccelerations); _jobDataSetCursorAcceleration = new JobSetAcceleration { ValueToSet = _cursorInputDeltas, AccumulatedAcceleration = _cursorAccelerations }; //update cursor friction _jobDataApplyCursorFriction = new JobApplyLinearAndConstantFriction { DeltaTime = deltaTime, LinearFriction = CursorLinearFriction, ConstantFriction = CursorConstantFriction, AccumulatedAcceleration = _cursorAccelerations, Velocity = _cursorVelocities }; _jobDataUpdateCursorPositions = new JobApplyAcceelrationAndVelocity { DeltaTime = deltaTime, AccumulatedAcceleration = _cursorAccelerations, VelocityInAndOut = _cursorVelocities, PositionInAndOut = _cursorPositions }; //Now we can update the blobs with the new state of the cursors _jobDataCursorsInfluenceBlobs = new JobCursorsInfluenceBlobs { CursorPositions = _cursorPositions, CursorVelocities = _cursorVelocities, CursorRadius = _cursorRadii, BlobPositions = _blobPositions, BlobAccelAccumulator = _blobAccelerations }; _jobDataApplyFrictionToBlobs = new JobApplyLinearAndConstantFriction { DeltaTime = deltaTime, //TODO: maybe I want friction based on acceleration (t*t) since that's the freshest part of this. //So, constant + linear(t) + accelerative (t*t) LinearFriction = GooPhysics.LinearFriction, ConstantFriction = GooPhysics.ConstantFriction, AccumulatedAcceleration = _blobAccelerations, Velocity = _blobVelocities }; //Blob sim gets updated _jobDataUpdateBlobPositions = new JobApplyAcceelrationAndVelocity { DeltaTime = deltaTime, AccumulatedAcceleration = _blobAccelerations, VelocityInAndOut = _blobVelocities, PositionInAndOut = _blobPositions }; //Output _jobDataDebugColorisationInt = new JobDebugColorisationInt() { minVal = 0, maxVal = 10, values = _blobGroupIDs, colors = _blobColors, }; _jobDataDebugColorisationKNNLength = new JobDebugColorisationKNNRangeQuery() { minVal = 0, maxVal = 10, values = _blobKNNNearestNeighbourQueryResults, colors = _blobColors, }; /* _jobDataDebugColorisationFloat = new JobDebugColorisationFloat * { * minVal = 0, * maxVal = 10, * values = _blobEdgeCount, * colors =_blobColors, * }*/ _jobDataDebugColorisationFloat2Magnitude = new JobDebugColorisationFloat2XY { maxVal = 10, values = _blobVelocities, colors = _blobColors }; _jobDataCopyBlobsToParticleSystem = new JopCopyBlobsToParticleSystem { colors = _blobColors, positions = _blobPositions, velocities = _blobVelocities }; _jobDataCopyCursorsToTransforms = new JobCopyBlobsToTransforms { BlobPos = _cursorPositions }; #region BoundsForCamera _jobDataCalculateAABB = new JobCalculateAABB() { Positions = _blobPositions, Bounds = _overallGooBounds }; #endregion // BoundsForCamera #endregion // Updates #endregion // JobDataSetup }
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); }
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(); }
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); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (cameraTransform == null) { cameraTransform = GameObject.Find("Main Camera").transform; } EntityManager.GetAllUniqueSharedComponentData(uniqueTypes); ComponentDataArray <SPHCollider> colliders = SPHColliderGroup.GetComponentDataArray <SPHCollider>(); int colliderCount = colliders.Length; for (int typeIndex = 1; typeIndex < uniqueTypes.Count; typeIndex++) { // Get the current chunk setting SPHParticle settings = uniqueTypes[typeIndex]; SPHCharacterGroup.SetFilter(settings); // Cache the data ComponentDataArray <Position> positions = SPHCharacterGroup.GetComponentDataArray <Position>(); ComponentDataArray <SPHVelocity> velocities = SPHCharacterGroup.GetComponentDataArray <SPHVelocity>(); int cacheIndex = typeIndex - 1; int particleCount = positions.Length; NativeMultiHashMap <int, int> hashMap = new NativeMultiHashMap <int, int>(particleCount, Allocator.TempJob); NativeArray <Position> particlesPosition = new NativeArray <Position>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <SPHVelocity> particlesVelocity = new NativeArray <SPHVelocity>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float3> particlesForces = new NativeArray <float3>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float> particlesPressure = new NativeArray <float>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float> particlesDensity = new NativeArray <float>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> particleIndices = new NativeArray <int>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> cellOffsetTableNative = new NativeArray <int>(cellOffsetTable, Allocator.TempJob); NativeArray <SPHCollider> copyColliders = new NativeArray <SPHCollider>(colliderCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Add new or dispose previous particle chunks PreviousParticle nextParticles = new PreviousParticle { hashMap = hashMap, particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesForces = particlesForces, particlesPressure = particlesPressure, particlesDensity = particlesDensity, particleIndices = particleIndices, cellOffsetTable = cellOffsetTableNative, copyColliders = copyColliders }; if (cacheIndex > previousParticles.Count - 1) { previousParticles.Add(nextParticles); } else { previousParticles[cacheIndex].hashMap.Dispose(); previousParticles[cacheIndex].particlesPosition.Dispose(); previousParticles[cacheIndex].particlesVelocity.Dispose(); previousParticles[cacheIndex].particlesForces.Dispose(); previousParticles[cacheIndex].particlesPressure.Dispose(); previousParticles[cacheIndex].particlesDensity.Dispose(); previousParticles[cacheIndex].particleIndices.Dispose(); previousParticles[cacheIndex].cellOffsetTable.Dispose(); previousParticles[cacheIndex].copyColliders.Dispose(); } previousParticles[cacheIndex] = nextParticles; // Copy the component data to native arrays CopyComponentData <Position> particlesPositionJob = new CopyComponentData <Position> { Source = positions, Results = particlesPosition }; JobHandle particlesPositionJobHandle = particlesPositionJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SPHVelocity> particlesVelocityJob = new CopyComponentData <SPHVelocity> { Source = velocities, Results = particlesVelocity }; JobHandle particlesVelocityJobHandle = particlesVelocityJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SPHCollider> copyCollidersJob = new CopyComponentData <SPHCollider> { Source = colliders, Results = copyColliders }; JobHandle copyCollidersJobHandle = copyCollidersJob.Schedule(colliderCount, 64, inputDeps); MemsetNativeArray <float> particlesPressureJob = new MemsetNativeArray <float> { Source = particlesPressure, Value = 0.0f }; JobHandle particlesPressureJobHandle = particlesPressureJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <float> particlesDensityJob = new MemsetNativeArray <float> { Source = particlesDensity, Value = 0.0f }; JobHandle particlesDensityJobHandle = particlesDensityJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <int> particleIndicesJob = new MemsetNativeArray <int> { Source = particleIndices, Value = 0 }; JobHandle particleIndicesJobHandle = particleIndicesJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <float3> particlesForcesJob = new MemsetNativeArray <float3> { Source = particlesForces, Value = new float3(0, 0, 0) }; JobHandle particlesForcesJobHandle = particlesForcesJob.Schedule(particleCount, 64, inputDeps); // Put positions into a hashMap HashPositions hashPositionsJob = new HashPositions { positions = particlesPosition, hashMap = hashMap.ToConcurrent(), cellRadius = settings.radius }; JobHandle hashPositionsJobHandle = hashPositionsJob.Schedule(particleCount, 64, particlesPositionJobHandle); JobHandle mergedPositionIndicesJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, particleIndicesJobHandle); MergeParticles mergeParticlesJob = new MergeParticles { particleIndices = particleIndices }; JobHandle mergeParticlesJobHandle = mergeParticlesJob.Schedule(hashMap, 64, mergedPositionIndicesJobHandle); JobHandle mergedMergedParticlesDensityPressure = JobHandle.CombineDependencies(mergeParticlesJobHandle, particlesPressureJobHandle, particlesDensityJobHandle); // Compute density pressure ComputeDensityPressure computeDensityPressureJob = new ComputeDensityPressure { particlesPosition = particlesPosition, densities = particlesDensity, pressures = particlesPressure, hashMap = hashMap, cellOffsetTable = cellOffsetTableNative, settings = settings }; JobHandle computeDensityPressureJobHandle = computeDensityPressureJob.Schedule(particleCount, 64, mergedMergedParticlesDensityPressure); JobHandle mergeComputeDensityPressureVelocityForces = JobHandle.CombineDependencies(computeDensityPressureJobHandle, particlesForcesJobHandle, particlesVelocityJobHandle); // Compute forces ComputeForces computeForcesJob = new ComputeForces { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesForces = particlesForces, particlesPressure = particlesPressure, particlesDensity = particlesDensity, cellOffsetTable = cellOffsetTableNative, hashMap = hashMap, settings = settings }; JobHandle computeForcesJobHandle = computeForcesJob.Schedule(particleCount, 64, mergeComputeDensityPressureVelocityForces); // Integrate Integrate integrateJob = new Integrate { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesDensity = particlesDensity, particlesForces = particlesForces }; JobHandle integrateJobHandle = integrateJob.Schedule(particleCount, 64, computeForcesJobHandle); JobHandle mergedIntegrateCollider = JobHandle.CombineDependencies(integrateJobHandle, copyCollidersJobHandle); // Compute Colliders ComputeColliders computeCollidersJob = new ComputeColliders { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, copyColliders = copyColliders, settings = settings }; JobHandle computeCollidersJobHandle = computeCollidersJob.Schedule(particleCount, 64, mergedIntegrateCollider); // Apply positions ApplyPositions applyPositionsJob = new ApplyPositions { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, positions = positions, velocities = velocities }; JobHandle applyPositionsJobHandle = applyPositionsJob.Schedule(particleCount, 64, computeCollidersJobHandle); inputDeps = applyPositionsJobHandle; } // Done uniqueTypes.Clear(); return(inputDeps); }
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); }
//La data del sphereParticle es compartiiiida protected override JobHandle OnUpdate(JobHandle inputDeps) { if (cameraTransform == null) { cameraTransform = GameObject.Find("Main Camera").transform; } EntityManager.GetAllUniqueSharedComponentData(uniqueTypes); ComponentDataArray <SMBCollider> colliders = SMBColliderGroup.GetComponentDataArray <SMBCollider>(); int colliderCount = colliders.Length; for (int typeIndex = 1; typeIndex < uniqueTypes.Count; typeIndex++) { // Get the current chunk setting SMBProperties settings = uniqueTypes[typeIndex]; //SMBDestination smbdestination = _destination[typeIndex]; SMBCharacterGroup.SetFilter(settings); // Cache the data ComponentDataArray <Position> positions = SMBCharacterGroup.GetComponentDataArray <Position>(); ComponentDataArray <SMBVelocity> velocities = SMBCharacterGroup.GetComponentDataArray <SMBVelocity>(); ComponentDataArray <SMBDestination> SMBdestinations = SMBCharacterGroup.GetComponentDataArray <SMBDestination>(); ComponentDataArray <SMBSspeed> SMBSspeeds = SMBCharacterGroup.GetComponentDataArray <SMBSspeed>(); ComponentDataArray <SMBPath> indexPaths = SMBCharacterGroup.GetComponentDataArray <SMBPath>(); int cacheIndex = typeIndex - 1; int particleCount = positions.Length; NativeMultiHashMap <int, int> hashMap = new NativeMultiHashMap <int, int>(particleCount, Allocator.TempJob); NativeArray <Position> particlesPosition = new NativeArray <Position>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <Position> finalposition = new NativeArray <Position>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <SMBVelocity> particlesVelocity = new NativeArray <SMBVelocity>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <SMBDestination> particlesDestination = new NativeArray <SMBDestination>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <SMBSspeed> particlesSspeed = new NativeArray <SMBSspeed>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <SMBPath> particlesindexPaths = new NativeArray <SMBPath>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float3> particlesForces = new NativeArray <float3>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float> particlesPressure = new NativeArray <float>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float> particlesDensity = new NativeArray <float>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> particleIndices = new NativeArray <int>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> cellOffsetTableNative = new NativeArray <int>(cellOffsetTable, Allocator.TempJob); NativeArray <SMBCollider> copyColliders = new NativeArray <SMBCollider>(colliderCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Add new or dispose previous particle chunks PreviousParticle nextParticles = new PreviousParticle { hashMap = hashMap, particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesDestination = particlesDestination, particlesSspeed = particlesSspeed, particlesindexPaths = particlesindexPaths, particlesForces = particlesForces, particlesPressure = particlesPressure, particlesDensity = particlesDensity, particleIndices = particleIndices, cellOffsetTable = cellOffsetTableNative, copyColliders = copyColliders }; if (cacheIndex > previousParticles.Count - 1) { previousParticles.Add(nextParticles); } else { previousParticles[cacheIndex].hashMap.Dispose(); previousParticles[cacheIndex].particlesPosition.Dispose(); previousParticles[cacheIndex].particlesVelocity.Dispose(); previousParticles[cacheIndex].particlesDestination.Dispose(); previousParticles[cacheIndex].particlesSspeed.Dispose(); previousParticles[cacheIndex].particlesindexPaths.Dispose(); previousParticles[cacheIndex].particlesForces.Dispose(); previousParticles[cacheIndex].particlesPressure.Dispose(); previousParticles[cacheIndex].particlesDensity.Dispose(); previousParticles[cacheIndex].particleIndices.Dispose(); previousParticles[cacheIndex].cellOffsetTable.Dispose(); previousParticles[cacheIndex].copyColliders.Dispose(); } previousParticles[cacheIndex] = nextParticles; // Copy the component data to native arrays CopyComponentData <Position> particlesPositionJob = new CopyComponentData <Position> { Source = positions, Results = particlesPosition }; JobHandle particlesPositionJobHandle = particlesPositionJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SMBVelocity> particlesVelocityJob = new CopyComponentData <SMBVelocity> { Source = velocities, Results = particlesVelocity }; JobHandle particlesVelocityJobHandle = particlesVelocityJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SMBDestination> particlesDestinationJob = new CopyComponentData <SMBDestination> { Source = SMBdestinations, Results = particlesDestination }; JobHandle particlesDestinationJobHandle = particlesDestinationJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SMBSspeed> particlesSspeedJob = new CopyComponentData <SMBSspeed> { Source = SMBSspeeds, Results = particlesSspeed }; JobHandle particlesSspeedJobHandle = particlesSspeedJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SMBCollider> copyCollidersJob = new CopyComponentData <SMBCollider> { Source = colliders, Results = copyColliders }; JobHandle copyCollidersJobHandle = copyCollidersJob.Schedule(colliderCount, 64, inputDeps); MemsetNativeArray <float> particlesPressureJob = new MemsetNativeArray <float> { Source = particlesPressure, Value = 0.0f }; JobHandle particlesPressureJobHandle = particlesPressureJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <float> particlesDensityJob = new MemsetNativeArray <float> { Source = particlesDensity, Value = 0.0f }; JobHandle particlesDensityJobHandle = particlesDensityJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <int> particleIndicesJob = new MemsetNativeArray <int> { Source = particleIndices, Value = 0 }; JobHandle particleIndicesJobHandle = particleIndicesJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <float3> particlesForcesJob = new MemsetNativeArray <float3> { Source = particlesForces, Value = new float3(0, 0, 0) }; JobHandle particlesForcesJobHandle = particlesForcesJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <Position> finalpositionJob = new MemsetNativeArray <Position> { Source = finalposition, Value = new Position { Value = new float3() } }; JobHandle finalpositionJobHandle = finalpositionJob.Schedule(particleCount, 64, inputDeps); //JobHandle computepathsJobHandle = particlesPositionJobHandle; if (first) { int index = 0, firsTriangle = 1; for (int i = 0; i < particleCount; ++i) { astar.cleanStructures(); astar.setOrigin(positions[i].Value); astar.setDestination(SMBdestinations[i].destination); astar.trianglePath2(); //Allpaths.AddRange(astar.trianglePath2()); wayPointsPath.AddRange(astar.getWayPoints()); int aux = wayPointsPath.Count; if (aux - index == 0) { firsTriangle = -1; } else { firsTriangle = 1; } Unity.Mathematics.Random ola = new Unity.Mathematics.Random(1); indexPaths[i] = new SMBPath { indexIni = index, indexFin = aux, NextPoint = new float3(), Firsttriangle = firsTriangle, recalculate = ola.NextInt(15), fordwarDir = new float3() }; index = aux; } first = false; } //Una vez llegado al destino ir a otro, funciona pero va muuuuy lento /*else * { * int index = 0, firsTriangle = 1, aux = 0; * int diff = 0; * for (int i = 0; i < particleCount; ++i) * { * index = indexPaths[i].indexIni + diff; * aux = indexPaths[i].indexFin + diff; * float3 NextPoint = indexPaths[i].NextPoint, fordwarDir = indexPaths[i].fordwarDir; * int recalculate = indexPaths[i].recalculate; * firsTriangle = indexPaths[i].Firsttriangle; * if (SMBdestinations[i].finished == 1) * { * firsTriangle = 1; * astar.cleanStructures(); * astar.setOrigin(positions[i].Value); * astar.setDestination(SMBdestinations[i].destinations2); * astar.trianglePath2(); * int count = 0; * if (i == 0) * { * wayPointsPath.RemoveRange(0, indexPaths[i].indexFin); * index = 0; * count = indexPaths[i].indexFin; * } * else * { * index = indexPaths[i - 1].indexFin; * count = indexPaths[i].indexFin + diff - indexPaths[i - 1].indexFin; * wayPointsPath.RemoveRange(indexPaths[i - 1].indexFin, count); * } * List<SMBWaypoint> wayaux = astar.getWayPoints(); * wayPointsPath.InsertRange(index, wayaux); * * aux = wayaux.Count; * * indexPaths[i] = new SMBPath { indexIni = index, indexFin = aux + index, NextPoint = new float3(), Firsttriangle = firsTriangle, recalculate = recalculate, fordwarDir = new float3() }; * SMBdestinations[i] = new SMBDestination {finished = 2, destinations2 = SMBdestinations[i].destinations2, destination = SMBdestinations[i].destination }; * diff += aux - count; * } * else indexPaths[i] = new SMBPath { indexIni = index, indexFin = aux, NextPoint = NextPoint, Firsttriangle = firsTriangle, recalculate = recalculate, fordwarDir = fordwarDir }; * } * }*/ NativeArray <SMBWaypoint> NwayPointspaths = new NativeArray <SMBWaypoint>(wayPointsPath.Count, Allocator.TempJob); //MemsetNativeArray<SMBWaypoint> waypointsJob = new MemsetNativeArray<SMBWaypoint> { Source = NwayPointspaths, Value = new SMBWaypoint { } }; //NativeArray<int>.Copy(Allpaths.ToArray(), paths); NativeArray <SMBWaypoint> .Copy(wayPointsPath.ToArray(), NwayPointspaths, wayPointsPath.Count); //CopyComponentData<SMBDestination> particlesDestinationJob = new CopyComponentData<SMBDestination> { Source = SMBdestinations, Results = particlesDestination }; //JobHandle particlesDestinationJobHandle = particlesDestinationJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SMBPath> particlesIndexPathJob = new CopyComponentData <SMBPath> { Source = indexPaths, Results = particlesindexPaths }; JobHandle particlesIndexPathJobHandle = particlesIndexPathJob.Schedule(particleCount, 64, inputDeps); // Put positions into a hashMap HashPositions hashPositionsJob = new HashPositions { positions = particlesPosition, hashMap = hashMap.ToConcurrent(), cellRadius = settings.radius }; JobHandle hashPositionsJobHandle = hashPositionsJob.Schedule(particleCount, 64, particlesPositionJobHandle); JobHandle mergedPositionIndicesJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, particleIndicesJobHandle); MergeParticles mergeParticlesJob = new MergeParticles { particleIndices = particleIndices }; JobHandle mergeParticlesJobHandle = mergeParticlesJob.Schedule(hashMap, 64, mergedPositionIndicesJobHandle); JobHandle mergedMergedParticlesDensityPressure = JobHandle.CombineDependencies(mergeParticlesJobHandle, particlesPressureJobHandle, particlesDensityJobHandle); // Compute density pressure ComputeDensityPressure computeDensityPressureJob = new ComputeDensityPressure { particlesPosition = particlesPosition, densities = particlesDensity, pressures = particlesPressure, hashMap = hashMap, cellOffsetTable = cellOffsetTableNative, settings = settings }; JobHandle computeDensityPressureJobHandle = computeDensityPressureJob.Schedule(particleCount, 64, mergedMergedParticlesDensityPressure); JobHandle mergeComputeDensityPressureVelocityForces = JobHandle.CombineDependencies(computeDensityPressureJobHandle, particlesForcesJobHandle, particlesVelocityJobHandle); // Compute forces ComputeForces computeForcesJob = new ComputeForces { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesForces = particlesForces, particlesPressure = particlesPressure, particlesDensity = particlesDensity, cellOffsetTable = cellOffsetTableNative, hashMap = hashMap, settings = settings }; JobHandle computeForcesJobHandle = computeForcesJob.Schedule(particleCount, 64, mergeComputeDensityPressureVelocityForces); // Integrate Integrate integrateJob = new Integrate { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesDensity = particlesDensity, particlesForces = particlesForces }; JobHandle integrateJobHandle = integrateJob.Schedule(particleCount, 64, computeForcesJobHandle); JobHandle mergedIntegrateCollider = JobHandle.CombineDependencies(integrateJobHandle, copyCollidersJobHandle); //JobHandle mergedIntegrateCollider = JobHandle.CombineDependencies(particlesPositionJobHandle, particlesVelocityJobHandle, copyCollidersJobHandle); // Compute Colliders ComputeColliders computeCollidersJob = new ComputeColliders { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, copyColliders = copyColliders, settings = settings }; JobHandle computeCollidersJobHandle = computeCollidersJob.Schedule(particleCount, 64, mergedIntegrateCollider); JobHandle allReady = JobHandle.CombineDependencies(computeCollidersJobHandle, particlesIndexPathJobHandle, particlesDestinationJobHandle); ComputeNewPoint computeNewPointJob = new ComputeNewPoint { particlesPosition = particlesPosition, waypoints = NwayPointspaths, indexPaths = particlesindexPaths, particlesDestination = particlesDestination }; JobHandle computeNewPointJobHandle = computeNewPointJob.Schedule(particleCount, 64, allReady); computeNewPointJobHandle = JobHandle.CombineDependencies(computeNewPointJobHandle, finalpositionJobHandle); RecomputeNewPoint RecomputeNewPointJob = new RecomputeNewPoint { particlesPosition = particlesPosition, waypoints = NwayPointspaths, indexPaths = particlesindexPaths }; JobHandle RecomputeNewPointJobHandle = RecomputeNewPointJob.Schedule(particleCount, 64, computeNewPointJobHandle); JobHandle preparedToComputePositions = JobHandle.CombineDependencies(RecomputeNewPointJobHandle, particlesSspeedJobHandle); ComputePosition computePositionJob = new ComputePosition { particlesPosition = particlesPosition, particlesDestination = particlesDestination, particlesSspeed = particlesSspeed, particlesVelocity = particlesVelocity, indexPaths = particlesindexPaths, hashMap = hashMap, settings = settings, cellOffsetTable = cellOffsetTableNative, finalPosition = finalposition }; JobHandle comptePositionJobHandle = computePositionJob.Schedule(particleCount, 64, preparedToComputePositions); // Apply positions ApplyPositions applyPositionsJob = new ApplyPositions { particlesPosition = finalposition, particlesVelocity = particlesVelocity, particlesindexPaths = particlesindexPaths, //particlesDestination = particlesDestination, particlesSspeed = particlesSspeed, positions = positions, velocities = velocities, indexPaths = indexPaths, SMBSspeeds = SMBSspeeds, //SMBdestinations = SMBdestinations, }; JobHandle applyPositionsJobHandle = applyPositionsJob.Schedule(particleCount, 64, comptePositionJobHandle); inputDeps = applyPositionsJobHandle; inputDeps.Complete(); NwayPointspaths.Dispose(); finalposition.Dispose(); } // Done uniqueTypes.Clear(); return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle input_deps) { float dt = Time.DeltaTime * SimulationManager.sim.speed_multiplier; float current_time = SimulationManager.sim.current_time; float day_time = SimulationManager.sim.day_time; var home_bound = SimulationManager.sim.home_bound; var wearing_mask = SimulationManager.sim.wearing_mask; var has_started = SimulationManager.sim.has_started; int person_count = SimulationManager.sim.person_count; Rect bounds = SimulationManager.sim.bounds; float interaction_radius = SimulationManager.sim.interaction_radius; float infection_rate_per_virus = SimulationManager.sim.infection_rate_per_virus; var max_hash = (int)(bounds.width * bounds.height / interaction_radius / interaction_radius); var hash_map = new NativeMultiHashMap <int, int>(person_count, Allocator.TempJob); var cell_index = new NativeArray <int>(person_count, Allocator.TempJob); var cell_virus = new NativeArray <float>(person_count, Allocator.TempJob); var cell_count = new NativeArray <int>(person_count, Allocator.TempJob); var cell_position = new NativeArray <float2>(person_count, Allocator.TempJob); var room_count = 13 * 13 * SimulationManager.sim.rooms_per_apartment * 4; var occupied_count = new NativeArray <int>(room_count, Allocator.TempJob); var occupied_virus = new NativeArray <float>(room_count, Allocator.TempJob); var occupied_antibodies = new NativeArray <float>(room_count, Allocator.TempJob); // Read data into NativeArrays. var read_pos_deps = Entities.WithAll <PersonData>().ForEach( (int entityInQueryIndex, in Translation R) => { cell_position[entityInQueryIndex] = new float2(R.Value.x, R.Value.z); }).Schedule(input_deps); var read_virus_deps = Entities.ForEach( (int entityInQueryIndex, in PersonData p) => { cell_virus[entityInQueryIndex] = p.virus; }).Schedule(input_deps); var initialize_cell_count_deps = new MemsetNativeArray <int> { Source = cell_count, Value = 1 }.Schedule(person_count, 64, input_deps); var initialize_occupied_count_deps = new MemsetNativeArray <int> { Source = occupied_count, Value = 1 }.Schedule(room_count, 64, input_deps); // Place people into the hash map. var parallel_hash_map = hash_map.AsParallelWriter(); var read_hash_deps = Entities.ForEach( (int entityInQueryIndex, in Translation R, in PersonData P) => { var pos = new float2(R.Value.x, R.Value.z) + new float2(bounds.min.x, bounds.min.y); int hash; if (P.is_home) { hash = max_hash + P.home_idx; } else { hash = (int)math.hash(new int2(math.floor(pos / interaction_radius))); } parallel_hash_map.Add(hash, entityInQueryIndex); }).Schedule(input_deps);
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); }
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) { var boidCount = m_Boids.boidTag.Length; var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var hashMap = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob); var copyTargetPositions = new NativeArray <Position>(m_Boids.boidTarget.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyObstaclePositions = new NativeArray <Position>(m_Obstacles.obstaclePositions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellSeparation = new NativeArray <Position>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstacleDistance = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstaclePositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellCount = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var hashPositionsJob = new HashPositions { positions = m_Boids.boidPositions, hashMap = hashMap, cellRadius = ECSBootstrapper.boidSettings.cellRadius }; var hashPositionsJobHandle = hashPositionsJob.Schedule(boidCount, 64, inputDeps); var initialCellSeparationJob = new CopyComponentData <Position> { Source = m_Boids.boidPositions, Results = cellSeparation }; var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(boidCount, 64, inputDeps); var initialCellCountJob = new MemsetNativeArray <int> { Source = cellCount, Value = 1 }; var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDeps); var initialCellBarrierJobHandle = JobHandle.CombineDependencies(initialCellSeparationJobHandle, initialCellCountJobHandle); var copyTargetPositionJob = new CopyTargetPositions { Source = m_Boids.boidTarget, Results = copyTargetPositions }; var copyTargetPositionsJobHandle = copyTargetPositionJob.Schedule(m_Boids.boidTarget.Length, 2, inputDeps); var copyObstaclePositionsJob = new CopyComponentData <Position> { Source = m_Obstacles.obstaclePositions, Results = copyObstaclePositions }; var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(m_Obstacles.obstaclePositions.Length, 2, inputDeps); var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle); var mergeCellsBarrierJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle); var mergeCellsJob = new MergeCells { cellIndices = cellIndices, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellCount = cellCount, obstaclePositions = copyObstaclePositions }; var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle); var steerJob = new Steer { cellIndices = cellIndices, //D settings = ECSBootstrapper.boidSettings, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions, dt = Time.deltaTime, positions = m_Boids.boidPositions, headings = m_Boids.boidHeadings, }; var steerJobHandle = steerJob.Schedule(boidCount, 64, mergeCellsJobHandle); steerJobHandle.Complete(); cellIndices.Dispose(); hashMap.Dispose(); copyTargetPositions.Dispose(); copyObstaclePositions.Dispose(); cellSeparation.Dispose(); cellObstacleDistance.Dispose(); cellObstaclePositionIndex.Dispose(); cellCount.Dispose(); return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { // reset values to -1 var clearArrayJob = new MemsetNativeArray <int> // MemsetNativeArray job assigns the same value to the whole array { Source = gridIndexArray, Value = -1 }; var clearArrayJobHandle = clearArrayJob.Schedule(ARRAY_SIZE, 64, inputDeps); // not sure what the 64 innerloop batch count means // fill index array job var fillJob = new FillDataArrayJob() { gridIndexData = gridIndexArray }; var fillJobHandle = fillJob.Schedule(this, clearArrayJobHandle); // makes sure the clearArrayJob is complete #region legacy slow /* * entities = MicrobeSpawner.entityArray; * centerPos = Object.FindObjectOfType<InputComponent>().transform.position; * globalOffset += .2f; // WTF IS THIS * * // update avoidance data and calculate force * * // THIS MAKES THE SYSTEM SLOW!!! * * for (int i = 0; i < MicrobeSpawner.total; i++) * { * MovementData indexForcePrevPos = EntityManager.GetComponentData<MovementData>(entities[i]); * Position position = EntityManager.GetComponentData<Position>(entities[i]); * entityPositionsArray[i] = position.Value; * * // remove old position from grid * int outerIndex = CoordsToOuterIndex( * (int)indexForcePrevPos.PreviousPosition.x, * (int)indexForcePrevPos.PreviousPosition.y); * * if (outerIndex >= 0 && outerIndex < gridIndexArray.Length) * { * for (int innerIndex = outerIndex; innerIndex < outerIndex + COLLISION_FORCES_PER_TILE; innerIndex++) * { * if (gridIndexArray[innerIndex] == indexForcePrevPos.Index) * { * gridIndexArray[innerIndex] = 0; * } * } * } * * // add new position to grid * outerIndex = CoordsToOuterIndex((int)position.Value.x, (int)position.Value.z); * if (outerIndex >= 0 && outerIndex < gridIndexArray.Length) * { * for (int innerIndex = outerIndex; innerIndex < outerIndex + COLLISION_FORCES_PER_TILE; innerIndex++) * { * if (gridIndexArray[innerIndex] == 0) * { * gridIndexArray[innerIndex] = indexForcePrevPos.Index; * } * } * } * }*/ #endregion // movement job var movementJob = new PositionJob(gridIndexArray, entityPositionsArray); var movementJobHandle = movementJob.Schedule(this, fillJobHandle); // makes sure the fillJob is complete return(movementJobHandle); //return movementJob.Schedule(this, inputDeps); }