protected override JobHandle OnUpdate(JobHandle inputDeps) { var projectileTranslations = m_projectilesQuery.ToComponentDataArray <Translation>(Allocator.TempJob); var projectileCollisions = m_projectilesQuery.ToComponentDataArray <CollisionSize>(Allocator.TempJob); var projectiles = m_projectilesQuery.ToEntityArray(Allocator.TempJob); poolLocations.Clear(); EntityManager.GetAllUniqueSharedComponentData <ProjectilePoolLocation>(poolLocations); if (projectileCollisions.Length > 0 && poolLocations.Count > 1) { var job = new ProjectileCollisionJob { ProjectileTranslations = projectileTranslations, ProjectileCollisions = projectileCollisions, Projectiles = projectiles, ECB = m_beginSimEcbSystem.CreateCommandBuffer().ToConcurrent(), PoolLocation = poolLocations[1].Value }; inputDeps = job.Schedule(this, inputDeps); m_projectilesQuery.AddDependency(inputDeps); m_beginSimEcbSystem.AddJobHandleForProducer(inputDeps); } else { projectileTranslations.Dispose(); projectileCollisions.Dispose(); projectiles.Dispose(); } return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle job) { spawnerTypes_.Clear(); EntityManager.GetAllUniqueSharedComponentData(spawnerTypes_); // Ignore 0 (prefab == Entity.null) for (int i = 1; i < spawnerTypes_.Count; ++i) { spawnerQuery_.SetFilter(spawnerTypes_[i]); //Debug.Log("Running shooter job"); job = new AutoBulletShooterSystemJob { commandBuffer = initBufferSystem_.CreateCommandBuffer().ToConcurrent(), bulletPrefab = spawnerTypes_[i].bulletPrefab, dt = Time.deltaTime, }.Schedule(spawnerQuery_, job); initBufferSystem_.AddJobHandleForProducer(job); spawnerQuery_.AddDependency(job); } return(job); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var job = new ScaleJob(); JobHandle jobHandler = job.Schedule(entitiesScaleGroup, inputDeps); entitiesScaleGroup.AddDependency(inputDeps); return(jobHandler); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var agentCount = agentQuery.CalculateEntityCount(); if (agentCount == 0) { agentQuery.ResetFilter(); return(inputDeps); } var hashMap = new NativeMultiHashMap <int, int>(agentCount, Allocator.TempJob); var parallelHashMap = hashMap.AsParallelWriter(); var hashJob = Entities .WithNone <NavAvoidant, NavPlanning>() .WithAll <NavLerping, Parent, LocalToParent>() .WithNativeDisableContainerSafetyRestriction(parallelHashMap) .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) => { parallelHashMap.Add( (int)math.hash(new int3(math.floor(localToWorld.Position / NavConstants.AVOIDANCE_CELL_RADIUS))), entityInQueryIndex ); }) .WithName("NavHashJob") .Schedule(inputDeps); agentQuery.AddDependency(hashJob); agentQuery.ResetFilter(); var avoidJob = new AvoidJob { DeltaSeconds = Time.DeltaTime, AgentEntityArray = agentQuery.ToEntityArray(Allocator.TempJob), AgentFromEntity = GetComponentDataFromEntity <NavAgent>(), RotationFromEntity = GetComponentDataFromEntity <Rotation>(true), LocalToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true), ParentFromEntity = GetComponentDataFromEntity <Parent>(true), PathBufferFromEntity = GetBufferFromEntity <NavPathBufferElement>(true), CommandBuffer = barrier.CreateCommandBuffer().ToConcurrent() }.Schedule(hashMap, 64, hashJob); avoidJob = hashMap.Dispose(avoidJob); barrier.AddJobHandleForProducer(avoidJob); return(avoidJob); }
protected override void OnUpdate() { particleQuery.AddDependency(Dependency); int entityCount = particleQuery.CalculateEntityCount(); // Do a sweap over all the entities and extract an entity which matches the "world" they are in // and also convert their locations to a 2D position on the grid var sharedEntityDetails = new NativeArray <Entity>(entityCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var entityLocations = new NativeArray <float2>(entityCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var groupEntitiesJob = Entities .WithStoreEntityQueryInField(ref particleQuery) .WithName("GrabParticleSpawnInfo") .ForEach((in int entityInQueryIndex, in NewLife lifeDetails, in Translation location) => { sharedEntityDetails[entityInQueryIndex] = lifeDetails.worldEntity; entityLocations[entityInQueryIndex] = new float2(location.Value.x, location.Value.z); }).ScheduleParallel(Dependency);
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityCommandBuffer.Concurrent commandBuffer = endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent(); BoundingVolume playerBounds = GetComponentDataFromEntity <BoundingVolume>(true)[GameHandler.playerEntity]; Health playerHealth = GetComponentDataFromEntity <Health>(true)[GameHandler.playerEntity]; Player player = GetComponentDataFromEntity <Player>(true)[GameHandler.playerEntity]; PlayerToHealthModifierCollisionJob pToHJob = new PlayerToHealthModifierCollisionJob() { player = GameHandler.playerEntity, playerBounds = playerBounds.volume, playerHealth = playerHealth, commandBuffer = commandBuffer }; JobHandle jobHandle = pToHJob.Schedule(this, inputDeps); EntityQuery bulletQuery = EntityManager.CreateEntityQuery(typeof(Bullet), ComponentType.ReadOnly <BoundingVolume>(), ComponentType.ReadOnly <HealthModifier>()); bulletQuery.AddDependency(jobHandle); BulletToDamageableCollisionJob bToDam = new BulletToDamageableCollisionJob() { commandBuffer = commandBuffer, bulletColliders = bulletQuery.ToComponentDataArray <BoundingVolume>(Allocator.TempJob), bulletHealthMods = bulletQuery.ToComponentDataArray <HealthModifier>(Allocator.TempJob), bulletInfos = bulletQuery.ToComponentDataArray <Bullet>(Allocator.TempJob), bullets = bulletQuery.ToEntityArray(Allocator.TempJob) }; jobHandle = bToDam.Schedule(this, jobHandle); ValidateLifeJob validateLifeJob = new ValidateLifeJob() { playerEntity = GameHandler.playerEntity, player = player, commandBuffer = commandBuffer }; jobHandle = validateLifeJob.Schedule(this, jobHandle); endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(jobHandle); return(jobHandle); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { t += Bootstrap.Instance.speed * Time.deltaTime; var job = new LoopAnimationJob() { Time = t, ShapeRadius = Bootstrap.Instance.shapeRadius, ShapeSides = Bootstrap.Instance.shapeSides, SideSize = Bootstrap.Instance.sideSize, Radius = Bootstrap.Instance.radius, Rings = Bootstrap.Instance.rings, CubesPerRing = Bootstrap.Instance.cubesPerRing }; JobHandle jobHandler = job.Schedule(entitiesTransformGroup, inputDeps); entitiesTransformGroup.AddDependency(inputDeps); return(jobHandler); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { BoidActionSort boidActionsSort = new BoidActionSort(); NonBoidActionSort nonBoidActionSort = new NonBoidActionSort(); EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes); int obstacleCount = m_ObstacleGroup.CalculateLength(); int targetCount = m_TargetGroup.CalculateLength(); // Ingore typeIndex 0, can't use the default for anything meaningful. for (int typeIndex = 1; typeIndex < m_UniqueTypes.Count; typeIndex++) { MainBoid uniqueBoidConfig = m_UniqueTypes[typeIndex]; m_BoidGroup.SetFilter(uniqueBoidConfig); int boidCount = m_BoidGroup.CalculateLength(); //some of this can be cached from last time to reduce component data calls. int cacheIndex = typeIndex - 1; //this was causing an undisposed allocation error //NativeArray<JobHandle> initializationJobHandles = new NativeArray<JobHandle>(5, Allocator.Temp); NativeArray <Heading> boidHeadings = m_BoidGroup.ToComponentDataArray <Heading>(Allocator.TempJob, out JobHandle initialCellAlignmentJobHandle); //TODO: make this into a 2d array so that the 2d positions doesnt have to be calculated all the time. NativeArray <Translation> boidPositions = m_BoidGroup.ToComponentDataArray <Translation>(Allocator.TempJob, out JobHandle initialCellSeparationJobHandle); NativeArray <Translation> copyTargetPositions = m_TargetGroup.ToComponentDataArray <Translation>(Allocator.TempJob, out JobHandle copyTargetPositionsJobHandle); NativeArray <Translation> copyObstaclePositions = m_ObstacleGroup.ToComponentDataArray <Translation>(Allocator.TempJob, out JobHandle copyObstaclePositionsJobHandle); // initializationJobHandles[0] = initialCellAlignmentJobHandle; // initializationJobHandles[1] = initialCellSeparationJobHandle; // initializationJobHandles[2] = copyTargetPositionsJobHandle; // initializationJobHandles[3] = copyObstaclePositionsJobHandle; NativeArray <BoidAction> orderedBoidActions = new NativeArray <BoidAction>(uniqueBoidConfig.boidActions.Length, Allocator.TempJob); orderedBoidActions.CopyFrom(uniqueBoidConfig.boidActions); NativeArray <NonBoidAction> orderedNonBoidActions = new NativeArray <NonBoidAction>(uniqueBoidConfig.boidActions.Length, Allocator.TempJob); orderedBoidActions.CopyFrom(uniqueBoidConfig.boidActions); orderedNonBoidActions.Sort(nonBoidActionSort); orderedBoidActions.Sort(boidActionsSort); var hashMap = new NativeHashMap <float3, int>(boidCount, Allocator.TempJob); var hashPositionsJob = new HashPositions { hashMap = hashMap.ToConcurrent() }; var hashPositionsJobHandle = hashPositionsJob.Schedule(m_BoidGroup, inputDeps); // initializationJobHandles[4] = hashPositionsJobHandle; var nextCells = new PrevCells { hashMap = hashMap, boidHeadings = boidHeadings, boidPositions = boidPositions, copyObstaclePositions = copyObstaclePositions, copyTargetPositions = copyTargetPositions, orderedBoidActions = orderedBoidActions, orderedNonBoidActions = orderedNonBoidActions, }; if (cacheIndex > (m_PrevCells.Count - 1)) { m_PrevCells.Add(nextCells); } else { m_PrevCells[cacheIndex].hashMap.Dispose(); m_PrevCells[cacheIndex].copyTargetPositions.Dispose(); m_PrevCells[cacheIndex].copyObstaclePositions.Dispose(); m_PrevCells[cacheIndex].boidHeadings.Dispose(); m_PrevCells[cacheIndex].boidPositions.Dispose(); m_PrevCells[cacheIndex].orderedBoidActions.Dispose(); m_PrevCells[cacheIndex].orderedNonBoidActions.Dispose(); } m_PrevCells[cacheIndex] = nextCells; JobHandle initialCellBarrierJobHandle = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, copyTargetPositionsJobHandle); JobHandle copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(initialCellBarrierJobHandle, copyObstaclePositionsJobHandle, hashPositionsJobHandle); Steer steerJob = new Steer { // boidActionFunctions = boidActionFunctions, //boidConfig = uniqueBoidConfig, boidIndexs = hashMap, boidHeadings = boidHeadings, boidPositions = boidPositions, orderedBoidActions = orderedBoidActions, orderedNonBoidActions = orderedNonBoidActions, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions, dt = Time.deltaTime }; JobHandle steerJobHandle = steerJob.Schedule(m_BoidGroup, copyTargetObstacleBarrierJobHandle); inputDeps = steerJobHandle; m_BoidGroup.AddDependency(inputDeps); } m_UniqueTypes.Clear(); return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle inputDependencies) { EntityManager.GetAllUniqueSharedComponentData(uniqueTypes); var obstacleCount = obstacleQuery.CalculateEntityCount(); var targetCount = targetQuery.CalculateEntityCount(); for (int i = 0; i < prevFrameHashmaps.Count; i++) { prevFrameHashmaps[i].Dispose(); } prevFrameHashmaps.Clear(); for (int hordeVariantIndex = 0; hordeVariantIndex < uniqueTypes.Count; hordeVariantIndex++) { var settings = uniqueTypes[hordeVariantIndex]; hordeQuery.SetFilter(settings); var hordeCount = hordeQuery.CalculateEntityCount(); if (hordeCount == 0) { continue; } //Debug.Log(hordeCount); #region Initial vars var hashMap = new NativeMultiHashMap <int, int>(hordeCount, Allocator.TempJob); var cellIndices = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstaclePositionIndex = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellTargetPositionIndex = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellCount = new NativeArray <int>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstacleDistance = new NativeArray <float>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellAlignment = new NativeArray <float3>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellSeparation = new NativeArray <float3>(hordeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyTargetPositions = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); #endregion #region Initial jobs var initialCellAlignmentJob = new CopyHeadings { headings = cellAlignment }; var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(hordeQuery, inputDependencies); var initialCellSeparationJob = new CopyPositions { positions = cellSeparation }; var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(hordeQuery, inputDependencies); var copyTargetPositionsJob = new CopyPositions { positions = copyTargetPositions }; var copyTargetPositionsJobHandle = copyTargetPositionsJob.Schedule(targetQuery, inputDependencies); var copyObstaclePositionsJob = new CopyPositions { positions = copyObstaclePositions }; var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(obstacleQuery, inputDependencies); prevFrameHashmaps.Add(hashMap); var hashPositionsJob = new HashPositions { hashMap = hashMap.AsParallelWriter(), cellRadius = settings.CellRadius }; var hashPositionsJobHandle = hashPositionsJob.Schedule(hordeQuery, inputDependencies); var initialCellCountJob = new MemsetNativeArray <int> { Source = cellCount, Value = 1 }; var initialCellCountJobHandle = initialCellCountJob.Schedule(hordeCount, 64, inputDependencies); #endregion var initialCellBarrierJobHandle = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle); var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle); var mergeCellsBarrierJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle); var mergeCellsJob = new MergeCells { cellIndices = cellIndices, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions }; var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle); var steerJob = new Steer { cellIndices = cellIndices, settings = settings, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions, dt = Time.deltaTime, }; var steerJobHandle = steerJob.Schedule(hordeQuery, mergeCellsJobHandle); inputDependencies = steerJobHandle; hordeQuery.AddDependency(inputDependencies); } uniqueTypes.Clear(); return(inputDependencies); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes); var obstacleCount = m_ObstacleGroup.CalculateLength(); var targetCount = m_TargetGroup.CalculateLength(); // Ignore typeIndex 0, can't use the default for anything meaningful. for (int typeIndex = 1; typeIndex < m_UniqueTypes.Count; typeIndex++) { var settings = m_UniqueTypes[typeIndex]; m_BoidGroup.SetFilter(settings); var boidCount = m_BoidGroup.CalculateLength(); var cacheIndex = typeIndex - 1; var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var hashMap = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob); var cellObstacleDistance = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstaclePositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellTargetPositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellCount = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellAlignment = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellSeparation = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyTargetPositions = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var initialCellAlignmentJob = new CopyHeadings { headings = cellAlignment }; var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(m_BoidGroup, inputDeps); var initialCellSeparationJob = new CopyPositions { positions = cellSeparation }; var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(m_BoidGroup, inputDeps); var copyTargetPositionsJob = new CopyPositions { positions = copyTargetPositions }; var copyTargetPositionsJobHandle = copyTargetPositionsJob.Schedule(m_TargetGroup, inputDeps); var copyObstaclePositionsJob = new CopyPositions { positions = copyObstaclePositions }; var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(m_ObstacleGroup, inputDeps); var nextCells = new PrevCells { cellIndices = cellIndices, hashMap = hashMap, copyObstaclePositions = copyObstaclePositions, copyTargetPositions = copyTargetPositions, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount }; if (cacheIndex > (m_PrevCells.Count - 1)) { m_PrevCells.Add(nextCells); } else { m_PrevCells[cacheIndex].hashMap.Dispose(); m_PrevCells[cacheIndex].cellIndices.Dispose(); m_PrevCells[cacheIndex].cellObstaclePositionIndex.Dispose(); m_PrevCells[cacheIndex].cellTargetPositionIndex.Dispose(); m_PrevCells[cacheIndex].copyTargetPositions.Dispose(); m_PrevCells[cacheIndex].copyObstaclePositions.Dispose(); m_PrevCells[cacheIndex].cellAlignment.Dispose(); m_PrevCells[cacheIndex].cellSeparation.Dispose(); m_PrevCells[cacheIndex].cellObstacleDistance.Dispose(); m_PrevCells[cacheIndex].cellCount.Dispose(); } m_PrevCells[cacheIndex] = nextCells; var hashPositionsJob = new HashPositions { hashMap = hashMap.ToConcurrent(), cellRadius = settings.CellRadius }; var hashPositionsJobHandle = hashPositionsJob.Schedule(m_BoidGroup, inputDeps); var initialCellCountJob = new MemsetNativeArray <int> { Source = cellCount, Value = 1 }; var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDeps); var initialCellBarrierJobHandle = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle); var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle); var mergeCellsBarrierJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle); var mergeCellsJob = new MergeCells { cellIndices = cellIndices, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions }; var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle); var steerJob = new Steer { cellIndices = nextCells.cellIndices, settings = settings, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions, dt = Time.deltaTime, }; var steerJobHandle = steerJob.Schedule(m_BoidGroup, mergeCellsJobHandle); inputDeps = steerJobHandle; m_BoidGroup.AddDependency(inputDeps); } m_UniqueTypes.Clear(); return(inputDeps); }
protected override void OnUpdate() { if (!m_DriverSystem.ClientDriver.IsCreated) { return; } PingClientUIBehaviour.UpdateStats(m_PingStats[0], m_PingStats[1]); if (PingClientUIBehaviour.ServerEndPoint.IsValid && m_ConnectionGroup.IsEmptyIgnoreFilter) { Dependency.Complete(); var ent = EntityManager.CreateEntity(); EntityManager.AddComponentData(ent, new PingClientConnectionComponentData { connection = m_DriverSystem.ClientDriver.Connect(PingClientUIBehaviour.ServerEndPoint) }); return; } var driver = m_DriverSystem.ClientDriver; var serverEP = PingClientUIBehaviour.ServerEndPoint; var pendingPings = m_PendingPings; var pingStats = m_PingStats; var frameTime = Time.ElapsedTime; var commandBuffer = m_Barrier.CreateCommandBuffer(); Entities.ForEach((Entity entity, ref PingClientConnectionComponentData connection) => { if (!serverEP.IsValid) { connection.connection.Disconnect(driver); commandBuffer.DestroyEntity(entity); return; } DataStreamReader strm; NetworkEvent.Type cmd; while ((cmd = connection.connection.PopEvent(driver, out strm)) != NetworkEvent.Type.Empty) { if (cmd == NetworkEvent.Type.Connect) { pendingPings[0] = new PendingPing { id = pingStats[0], time = frameTime }; if (driver.BeginSend(connection.connection, out var pingData) == 0) { pingData.WriteInt(pingStats[0]); driver.EndSend(pingData); } pingStats[0] = pingStats[0] + 1; } else if (cmd == NetworkEvent.Type.Data) { pingStats[1] = (int)((frameTime - pendingPings[0].time) * 1000); connection.connection.Disconnect(driver); commandBuffer.DestroyEntity(entity); } else if (cmd == NetworkEvent.Type.Disconnect) { commandBuffer.DestroyEntity(entity); } } }).Schedule(); m_Barrier.AddJobHandleForProducer(Dependency); m_ServerConnectionGroup.AddDependency(Dependency); }
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) { if (!controller) { controller = BoidControllerECSJobsFast.Instance; } if (controller) { int boidCount = boidGroup.CalculateEntityCount(); var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellBoidCount = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var boidPositions = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var boidHeadings = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var hashMap = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob); var positionsAndHeadingsCopyJob = new CopyPositionsAndHeadingsInBuffer { boidPositions = boidPositions, boidHeadings = boidHeadings }; JobHandle positionsAndHeadingsCopyJobHandle = positionsAndHeadingsCopyJob.Schedule(boidGroup, inputDeps); quaternion randomHashRotation = quaternion.Euler( UnityEngine.Random.Range(-360f, 360f), UnityEngine.Random.Range(-360f, 360f), UnityEngine.Random.Range(-360f, 360f) ); float offsetRange = controller.boidPerceptionRadius / 2f; float3 randomHashOffset = new float3( UnityEngine.Random.Range(-offsetRange, offsetRange), UnityEngine.Random.Range(-offsetRange, offsetRange), UnityEngine.Random.Range(-offsetRange, offsetRange) ); var hashPositionsJob = new HashPositionsToHashMap { hashMap = hashMap.AsParallelWriter(), cellRotationVary = randomHashRotation, positionOffsetVary = randomHashOffset, cellRadius = controller.boidPerceptionRadius, }; JobHandle hashPositionsJobHandle = hashPositionsJob.Schedule(boidGroup, inputDeps); // Proceed when these two jobs have been completed JobHandle copyAndHashJobHandle = JobHandle.CombineDependencies( positionsAndHeadingsCopyJobHandle, hashPositionsJobHandle ); var mergeCellsJob = new MergeCellsJob { indicesOfCells = cellIndices, cellPositions = boidPositions, cellHeadings = boidHeadings, cellCount = cellBoidCount, }; JobHandle mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, copyAndHashJobHandle); var moveJob = new MoveBoids { deltaTime = Time.DeltaTime, boidSpeed = controller.boidSpeed, separationWeight = controller.separationWeight, alignmentWeight = controller.alignmentWeight, cohesionWeight = controller.cohesionWeight, cageSize = controller.cageSize, cageAvoidDist = controller.avoidWallsTurnDist, cageAvoidWeight = controller.avoidWallsWeight, cellSize = controller.boidPerceptionRadius, cellIndices = cellIndices, positionSumsOfCells = boidPositions, headingSumsOfCells = boidHeadings, cellBoidCount = cellBoidCount, }; JobHandle moveJobHandle = moveJob.Schedule(boidGroup, mergeCellsJobHandle); moveJobHandle.Complete(); hashMap.Dispose(); inputDeps = moveJobHandle; boidGroup.AddDependency(inputDeps); return(inputDeps); } else { return(inputDeps); } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes); var obstacleCount = m_ObstacleQuery.CalculateEntityCount(); var targetCount = m_TargetQuery.CalculateEntityCount(); // Cannot call [DeallocateOnJobCompletion] on Hashmaps yet, so doing own cleanup here // of the hashes created in the previous iteration. for (int i = 0; i < m_PrevFrameHashmaps.Count; ++i) { m_PrevFrameHashmaps[i].Dispose(); } m_PrevFrameHashmaps.Clear(); // Each variant of the Boid represents a different value of the SharedComponentData and is self-contained, // meaning Boids of the same variant only interact with one another. Thus, this loop processes each // variant type individually. for (int boidVariantIndex = 0; boidVariantIndex < m_UniqueTypes.Count; boidVariantIndex++) { var settings = m_UniqueTypes[boidVariantIndex]; m_BoidQuery.SetFilter(settings); var boidCount = m_BoidQuery.CalculateEntityCount(); if (boidCount == 0) { // Early out. If the given variant includes no Boids, move on to the next loop. // For example, variant 0 will always exit early bc it's it represents a default, uninitialized // Boid struct, which does not appear in this sample. continue; } // The following calculates spatial cells of neighboring Boids // note: working with a sparse grid and not a dense bounded grid so there // are no predefined borders of the space. var hashMap = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob); var cellIndices = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstaclePositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellTargetPositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellCount = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellObstacleDistance = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellAlignment = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cellSeparation = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyTargetPositions = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var copyObstaclePositions = new NativeArray <float3>(obstacleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // The following jobs all run in parallel because the same JobHandle is passed for their // input dependencies when the jobs are scheduled; thus, they can run in any order (or concurrently). // The concurrency is property of how they're scheduled, not of the job structs themselves. var initialCellAlignmentJob = new CopyHeadings { headings = cellAlignment }; var initialCellAlignmentJobHandle = initialCellAlignmentJob.Schedule(m_BoidQuery, inputDeps); var initialCellSeparationJob = new CopyPositions { positions = cellSeparation }; var initialCellSeparationJobHandle = initialCellSeparationJob.Schedule(m_BoidQuery, inputDeps); var copyTargetPositionsJob = new CopyPositions { positions = copyTargetPositions }; var copyTargetPositionsJobHandle = copyTargetPositionsJob.Schedule(m_TargetQuery, inputDeps); var copyObstaclePositionsJob = new CopyPositions { positions = copyObstaclePositions }; var copyObstaclePositionsJobHandle = copyObstaclePositionsJob.Schedule(m_ObstacleQuery, inputDeps); // Cannot call [DeallocateOnJobCompletion] on Hashmaps yet, so adding resolved hashes to the list // so that theyre usable in the upcoming cell jobs and also have a straight forward cleanup. m_PrevFrameHashmaps.Add(hashMap); // setting up the jobs for position and cell count var hashPositionsJob = new HashPositions { hashMap = hashMap.AsParallelWriter(), cellRadius = settings.CellRadius }; var hashPositionsJobHandle = hashPositionsJob.Schedule(m_BoidQuery, inputDeps); var initialCellCountJob = new MemsetNativeArray <int> { Source = cellCount, Value = 1 }; var initialCellCountJobHandle = initialCellCountJob.Schedule(boidCount, 64, inputDeps); var initialCellBarrierJobHandle = JobHandle.CombineDependencies(initialCellAlignmentJobHandle, initialCellSeparationJobHandle, initialCellCountJobHandle); var copyTargetObstacleBarrierJobHandle = JobHandle.CombineDependencies(copyTargetPositionsJobHandle, copyObstaclePositionsJobHandle); var mergeCellsBarrierJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, initialCellBarrierJobHandle, copyTargetObstacleBarrierJobHandle); var mergeCellsJob = new MergeCells { cellIndices = cellIndices, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions }; var mergeCellsJobHandle = mergeCellsJob.Schedule(hashMap, 64, mergeCellsBarrierJobHandle); var steerJob = new Steer { cellIndices = cellIndices, settings = settings, cellAlignment = cellAlignment, cellSeparation = cellSeparation, cellObstacleDistance = cellObstacleDistance, cellObstaclePositionIndex = cellObstaclePositionIndex, cellTargetPositionIndex = cellTargetPositionIndex, cellCount = cellCount, targetPositions = copyTargetPositions, obstaclePositions = copyObstaclePositions, dt = Time.deltaTime, }; var steerJobHandle = steerJob.Schedule(m_BoidQuery, mergeCellsJobHandle); inputDeps = steerJobHandle; m_BoidQuery.AddDependency(inputDeps); } m_UniqueTypes.Clear(); return(inputDeps); }
protected override void OnUpdate() { if (Camera.main == null) { return; } var lineList = m_LineList; Camera.main.RemoveCommandBuffers(CameraEvent.AfterEverything); Camera.main.AddCommandBuffer(CameraEvent.AfterEverything, m_CommandBuffer); if (lineList.Length > MaxLines) { Debug.LogWarning("Trying to render " + lineList.Length + " but limit is " + MaxLines); lineList.ResizeUninitialized(MaxLines); } var curOffset = m_RenderOffset[0]; NativeArray <Line> lines = lineList; m_Material.SetFloat("offsetX", curOffset.x); m_Material.SetFloat("offsetY", curOffset.y); m_Material.SetFloat("screenWidth", Screen.width); m_Material.SetFloat("screenHeight", Screen.height); m_Material.SetBuffer("lines", m_ComputeBuffer); m_ComputeBuffer.SetData(lines); m_CommandBuffer.Clear(); m_CommandBuffer.DrawProcedural(Matrix4x4.identity, m_Material, -1, MeshTopology.Triangles, lineList.Length * 6); lineList.Clear(); JobHandle levelHandle; var list = m_LineList; var queue = m_LineQueue; var renderOffset = m_RenderOffset; var renderSize = new float2(Screen.width, Screen.height); var deltaTime = Time.DeltaTime; var level = m_LevelGroup.ToComponentDataArrayAsync <LevelComponent>(Allocator.TempJob, out levelHandle); var copyToListJob = Entities.WithReadOnly(level).WithDeallocateOnJobCompletion(level).ForEach( (ref LineRendererComponentData lineData) => { if (level.Length > 0) { list.Add(new Line(new float2(0, 0), new float2(level[0].width, 0), new float4(1, 0, 0, 1), 5)); list.Add(new Line(new float2(0, 0), new float2(0, level[0].height), new float4(1, 0, 0, 1), 5)); list.Add(new Line(new float2(0, level[0].height), new float2(level[0].width, level[0].height), new float4(1, 0, 0, 1), 5)); list.Add(new Line(new float2(level[0].width, 0), new float2(level[0].width, level[0].height), new float4(1, 0, 0, 1), 5)); } var offset = renderOffset[0]; var target = lineData.targetOffset; renderOffset[1] = target; float maxPxPerSec = 500; if (math.any(offset != target)) { if (lineData.teleport != 0) { offset = target; } else { float2 delta = (target - offset); float deltaLen = math.length(delta); float maxDiff = maxPxPerSec * deltaTime; if (deltaLen > maxDiff || deltaLen < -maxDiff) { delta *= maxDiff / deltaLen; } offset += delta; } renderOffset[0] = offset; } Line line; while (queue.TryDequeue(out line)) { if ((line.start.x < offset.x - line.width && line.end.x < offset.x - line.width) || (line.start.x > offset.x + renderSize.x + line.width && line.end.x > offset.x + renderSize.x + line.width) || (line.start.y < offset.y - line.width && line.end.y < offset.y - line.width) || (line.start.y > offset.y + renderSize.y + line.width && line.end.y > offset.y + renderSize.y + line.width)) { continue; } list.Add(line); } }).Schedule(JobHandle.CombineDependencies(Dependency, levelHandle)); Dependency = copyToListJob; m_LineGroup.AddDependency(Dependency); }
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); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityCommandBuffer.Concurrent commandBuffer = endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent(); BoundingVolume playerBounds = GetComponentDataFromEntity <BoundingVolume>(true)[GameHandler.playerEntity]; HealthFloat playerHealth = GetComponentDataFromEntity <HealthFloat>(true)[GameHandler.playerEntity]; Player player = GetComponentDataFromEntity <Player>(true)[GameHandler.playerEntity]; // job for collision between player and enemies Entity playerEntity = GameHandler.playerEntity; JobHandle jobHandle = Entities .WithNone <Bullet>() .ForEach((Entity entity, int entityInQueryIndex, ref BoundingVolume vol, ref HealthModifier healthMod) => { if (vol.volume.Intersects(playerBounds.volume)) { // there was a collision, modify the player's health Utils.ModifyHealth(ref playerHealth, healthMod.value); commandBuffer.SetComponent <HealthFloat>(entityInQueryIndex, playerEntity, playerHealth); // get rid of the damager commandBuffer.DestroyEntity(entityInQueryIndex, entity); } }).Schedule(inputDeps); EntityQuery bulletQuery = EntityManager.CreateEntityQuery(typeof(Bullet), ComponentType.ReadOnly <BoundingVolume>(), ComponentType.ReadOnly <HealthModifier>()); bulletQuery.AddDependency(jobHandle); NativeArray <BoundingVolume> bulletColliders = bulletQuery.ToComponentDataArray <BoundingVolume>(Allocator.TempJob); NativeArray <HealthModifier> bulletHealthMods = bulletQuery.ToComponentDataArray <HealthModifier>(Allocator.TempJob); NativeArray <Bullet> bulletInfos = bulletQuery.ToComponentDataArray <Bullet>(Allocator.TempJob); NativeArray <Entity> bullets = bulletQuery.ToEntityArray(Allocator.TempJob); // job for checking collisions between enemies and bullets jobHandle = Entities .WithDeallocateOnJobCompletion(bulletColliders) .WithDeallocateOnJobCompletion(bulletHealthMods) .WithDeallocateOnJobCompletion(bulletInfos) .WithDeallocateOnJobCompletion(bullets) .WithReadOnly(bulletColliders) .WithReadOnly(bulletHealthMods) .WithReadOnly(bulletInfos) .WithReadOnly(bullets) .WithNone <Player>() .WithAll <Enemy>() .ForEach((Entity entity, int entityInQueryIndex, ref BoundingVolume damageableCollider, ref HealthFloat damageableHealth) => { for (int i = 0; i < bulletColliders.Length; i++) { // bullet isn't active, leave if (!bulletInfos[i].isActive) { continue; } if (damageableCollider.volume.Intersects(bulletColliders[i].volume)) { // bullet hit a damageable, reduce it's health Utils.ModifyHealth(ref damageableHealth, bulletHealthMods[i].value); // deactivate the bullet Bullet b = bulletInfos[i]; b.isActive = false; b.age = 0; commandBuffer.SetComponent <Bullet>(entityInQueryIndex, bullets[i], b); } } }).Schedule(jobHandle); jobHandle.Complete(); jobHandle = Entities .ForEach((Entity entity, int entityInQueryIndex, ref Enemy enemy, ref HealthFloat health) => { if (health.curr <= 0) { // destroy any entity who's health has dropped below 0 commandBuffer.DestroyEntity(entityInQueryIndex, entity); player.score += enemy.points; commandBuffer.SetComponent <Player>(entityInQueryIndex, playerEntity, player); } }).Schedule(jobHandle); jobHandle.Complete(); endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(jobHandle); return(jobHandle); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes); // var a = EntityManager.GetSharedComponentOrderVersion<MoveActions> (m_UniqueTypes[0]); // var b = EntityManager.GetSharedComponentOrderVersion<MoveActions> (m_UniqueTypes[2]); foreach (var uniqueType in m_UniqueTypes) { Debug.Log(uniqueType + " ID :" + EntityManager.GetSharedComponentOrderVersion <MoveActions>(uniqueType)); } Debug.Log("unique types:" + m_UniqueTypes.Count); //we start at one because the first one is simply the uninitialised version if (m_UniqueTypes.Count > 1) { for (int i = 1; i < m_UniqueTypes.Count; i++) { // Debug.Log ("distance: " + ArrayToString( m_UniqueTypes[i].distances)); // Debug.Log ("rotations: " + ArrayToString(m_UniqueTypes[i].rotations)); m_MoveActionsGroup.SetFilter(m_UniqueTypes[i]); int cacheIndex = i - 1; NativeArray <float> moveActionsDistances = new NativeArray <float>(1, Allocator.TempJob); NativeArray <float> moveActionsRotations = new NativeArray <float>(1, Allocator.TempJob); /* if (m_UniqueTypes[i].distances.Length != m_UniqueTypes[i].rotations.Length) { Debug.LogError ("there must be a rotation for each direction given"); } * if (m_UniqueTypes[i].distances.Length > 0) { moveActionsDistances = new NativeArray<float> (m_UniqueTypes[i].distances, Allocator.TempJob); } * else { Debug.LogError ("movactions distance has no data, without any actions this will fail."); } * if (m_UniqueTypes[i].rotations.Length > 0) { moveActionsRotations = new NativeArray<float> (m_UniqueTypes[i].rotations, Allocator.TempJob); } * else { Debug.LogError ("movactions rotations has no data, without any actions this will fail."); } */ // var tran else { Debug.LogError("movactions has no data, without any actiosn this will fail.") }slation = m_MoveActionsGroup.ToComponentDataArray<Translation> (Allocator.TempJob, out JobHandle getTranslationJobHandle); // var combinedHandles = JobHandle.CombineDependencies (inputDeps, getTranslationJobHandle); var moveActions = m_UniqueTypes[i]; //Essentially what this is doing is checking each time the job runs if the var nextActions = new PreviousActions { MoveActionsDistances = moveActionsDistances, MoveActionsRotations = moveActionsRotations }; if (cacheIndex > (m_previousActions.Count - 1)) { m_previousActions.Add(nextActions); } else { m_previousActions[cacheIndex].MoveActionsDistances.Dispose(); m_previousActions[cacheIndex].MoveActionsRotations.Dispose(); } m_previousActions[cacheIndex] = nextActions; ExecuteActions executeActionsJob = new ExecuteActions { deltaTime = Time.deltaTime, // storableEntityData = m_storeableEntityData, // postion = translation, //moveActions = m_UniqueTypes[i], rotations = moveActionsRotations, distances = moveActionsDistances, CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer() }; JobHandle executeActionsJobHandle = executeActionsJob.Schedule(this, inputDeps); inputDeps = executeActionsJobHandle; m_EntityCommandBufferSystem.AddJobHandleForProducer(inputDeps); m_MoveActionsGroup.AddDependency(inputDeps); //moveActionsRotations.Dispose(); // moveActionsDistances.Dispose(); } } m_UniqueTypes.Clear(); return(inputDeps); }
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); }