private JobHandle BuildRadarLayer(FactionMember factionMember, out CollisionLayer layer, JobHandle inputDeps) { m_radars.SetSharedComponentFilter(factionMember); int count = m_radars.CalculateEntityCount(); var bodies = new NativeArray <ColliderBody>(count, Allocator.TempJob); var aabbs = new NativeArray <Aabb>(count, Allocator.TempJob); var jh = Entities.WithAll <AiRadarTag>().WithSharedComponentFilter(factionMember).WithStoreEntityQueryInField(ref m_radars) .ForEach((Entity e, int entityInQueryIndex, in AiShipRadar radar, in LocalToWorld ltw) => { var transform = new RigidTransform(quaternion.LookRotationSafe(ltw.Forward, ltw.Up), ltw.Position); var sphere = new SphereCollider(0f, radar.distance); if (radar.cosFov < 0f) { //Todo: Create tighter bounds here too. aabbs[entityInQueryIndex] = Physics.CalculateAabb(sphere, transform); } else { //Compute aabb of vertex and spherical cap points which are extreme points float3 forward = math.forward(transform.rot); bool3 positiveOnSphereCap = forward > radar.cosFov; bool3 negativeOnSphereCap = -forward > radar.cosFov; float3 min = math.select(0f, -radar.distance, negativeOnSphereCap); float3 max = math.select(0f, radar.distance, positiveOnSphereCap); Aabb aabb = new Aabb(min, max); //Compute aabb of circle base float4 cos = new float4(forward, radar.cosFov); float4 sinSq = 1f - (cos * cos); float4 sin = math.sqrt(sinSq); float3 center = forward * radar.distance * radar.cosFov; float radius = radar.distance * sin.w; float3 extents = sin.xyz * radius; min = center - extents; max = center + extents; aabb.min = math.min(aabb.min, min) + transform.pos; aabb.max = math.max(aabb.max, max) + transform.pos; aabbs[entityInQueryIndex] = aabb; } bodies[entityInQueryIndex] = new ColliderBody { collider = sphere, entity = e, transform = transform }; }).ScheduleParallel(inputDeps);
protected override void OnUpdate() { Entities.WithStructuralChanges().WithAll <FactionTag>().ForEach((Entity entity, ref Faction faction) => { var factionMember = new FactionMember { factionEntity = entity }; m_aiQuery.SetSharedComponentFilter(factionMember); m_playerQuery.SetSharedComponentFilter(factionMember); if (faction.playerPrefab != Entity.Null && !m_playerQuery.IsEmpty) { var newPlayerShip = EntityManager.Instantiate(faction.playerPrefab); AddSharedComponentDataToLinkedGroup(newPlayerShip, factionMember); SpawnPlayer(newPlayerShip); faction.remainingReinforcements--; } { int spawnCount = m_aiQuery.CalculateEntityCount(); var newShipPrefab = EntityManager.Instantiate(faction.aiPrefab); EntityManager.AddComponent <NewFleetTag>(newShipPrefab); AddSharedComponentDataToLinkedGroup(newShipPrefab, factionMember); var newShips = EntityManager.Instantiate(newShipPrefab, spawnCount, Allocator.TempJob); EntityManager.DestroyEntity(newShipPrefab); SpawnAi(newShips); newShips.Dispose(); faction.remainingReinforcements -= spawnCount; } m_aiQuery.ResetFilter(); m_playerQuery.ResetFilter(); }).Run(); EntityManager.RemoveComponent <NewFleetTag>(m_aiQuery); }
protected override void OnUpdate() { Profiler.BeginSample("AiShipRadarScanSystem_OnUpdate"); var backup = Dependency; Dependency = default; Entities.WithAll <FactionTag>().WithStoreEntityQueryInField(ref m_factions).ForEach((Entity entity, int entityInQueryIndex) => { if (entityInQueryIndex == 0) { Dependency = backup; } m_factionsCache.Add(EntityManager.GetCollectionComponent <FactionShipsCollisionLayer>(entity, true)); }).WithoutBurst().Run(); var factionEntities = m_factions.ToEntityArray(Allocator.TempJob); var wallLayer = sceneGlobalEntity.GetCollectionComponent <WallCollisionLayer>(true).layer; var radarsCdfe = GetComponentDataFromEntity <AiShipRadar>(true); var radarScanResultsCdfe = GetComponentDataFromEntity <AiShipRadarScanResults>(false); var ltwCdfe = GetComponentDataFromEntity <LocalToWorld>(true); //Todo: IJobChunk with MemClear? Entities.WithAll <AiRadarTag>().ForEach((ref AiShipRadarScanResults results) => { results = default; results.nearestEnemy = Entity.Null; }).WithName("ScanClear").ScheduleParallel(); JobHandle rootDependency = Dependency; var finalHandles = new NativeList <JobHandle>(Allocator.TempJob); JobHandle resultsHandle = Dependency; for (int i = 0; i < factionEntities.Length; i++) { Profiler.BeginSample($"faction_A_{i}"); var factionMember = new FactionMember { factionEntity = factionEntities[i] }; var buildRadarLayerJh = BuildRadarLayer(factionMember, out CollisionLayer radarLayer, rootDependency); var friendsLineOfSightBodies = new NativeList <ColliderBody>(Allocator.TempJob); var friendsOccluded = new NativeList <bool>(Allocator.TempJob); var scanFriendsProcessor = new ScanFriendsProcessor { lineOfSightBodies = friendsLineOfSightBodies, radars = radarsCdfe }; var friendsJh = Physics.FindPairs(radarLayer, m_factionsCache[i].layer, scanFriendsProcessor).ScheduleSingle(buildRadarLayerJh); var prepFriendsVisibilityJob = new ResizeOccludedListToBodySizeJob { lineOfSightBodies = friendsLineOfSightBodies, occluded = friendsOccluded }; var prepFriendsJh1 = prepFriendsVisibilityJob.Schedule(friendsJh); var prepFriendsJh2 = Physics.BuildCollisionLayer(friendsLineOfSightBodies.AsDeferredJobArray()).WithRemapArray(out NativeArray <int> friendsLosBodiesSrcIndices, Allocator.TempJob) .ScheduleParallel(out CollisionLayer friendsLineOfSightLayer, Allocator.TempJob, friendsJh); var scanFriendsVisibileProcessor = new ScanLineOfSightProcessor { occluded = friendsOccluded.AsDeferredJobArray(), remapSrcIndices = friendsLosBodiesSrcIndices }; friendsJh = Physics.FindPairs(friendsLineOfSightLayer, wallLayer, scanFriendsVisibileProcessor) .ScheduleParallel(JobHandle.CombineDependencies(prepFriendsJh1, prepFriendsJh2)); var friendsJh1 = friendsLineOfSightLayer.Dispose(friendsJh); var friendsJh2 = friendsLosBodiesSrcIndices.Dispose(friendsJh); var updateFriendsJob = new UpdateFriendsJob { lineOfSightBodies = friendsLineOfSightBodies.AsDeferredJobArray(), occluded = friendsOccluded.AsDeferredJobArray(), radarScanResultsCdfe = radarScanResultsCdfe }; resultsHandle = updateFriendsJob.Schedule(JobHandle.CombineDependencies(friendsJh1, friendsJh2, resultsHandle)); finalHandles.Add(friendsLineOfSightBodies.Dispose(resultsHandle)); finalHandles.Add(friendsOccluded.Dispose(resultsHandle)); for (int j = 0; j < factionEntities.Length; j++) { if (j == i) { continue; } var enemiesLineOfSightBodies = new NativeList <ColliderBody>(Allocator.TempJob); var enemiesOccluded = new NativeList <bool>(Allocator.TempJob); var scannedEnemies = new NativeList <ScannedEnemy>(Allocator.TempJob); var scanEnemiesProcessor = new ScanEnemiesProcessor { lineOfSightBodies = enemiesLineOfSightBodies, radars = radarsCdfe, scannedEnemies = scannedEnemies }; var enemiesJh = Physics.FindPairs(radarLayer, m_factionsCache[j].layer, scanEnemiesProcessor).ScheduleSingle(buildRadarLayerJh); var prepEnemiesVisibilityJob = new ResizeOccludedListToBodySizeJob { lineOfSightBodies = enemiesLineOfSightBodies, occluded = enemiesOccluded }; var prepEnemiesJh1 = prepEnemiesVisibilityJob.Schedule(enemiesJh); var prepEnemiesJh2 = Physics.BuildCollisionLayer(enemiesLineOfSightBodies.AsDeferredJobArray()).WithRemapArray(out NativeArray <int> enemiesLosBodiesSrcIndices, Allocator.TempJob) .ScheduleParallel(out CollisionLayer enemiesLineOfSightLayer, Allocator.TempJob, friendsJh); var scanEnemiesVisibileProcessor = new ScanLineOfSightProcessor { occluded = enemiesOccluded.AsDeferredJobArray(), remapSrcIndices = enemiesLosBodiesSrcIndices }; enemiesJh = Physics.FindPairs(enemiesLineOfSightLayer, wallLayer, scanEnemiesVisibileProcessor) .ScheduleParallel(JobHandle.CombineDependencies(prepEnemiesJh1, prepEnemiesJh2)); var enemiesJh1 = enemiesLineOfSightLayer.Dispose(enemiesJh); var enemiesJh2 = enemiesLosBodiesSrcIndices.Dispose(enemiesJh); var updateEnemiesJob = new UpdateEnemiesJob { lineOfSightBodies = enemiesLineOfSightBodies.AsDeferredJobArray(), ltwCdfe = ltwCdfe, occluded = enemiesOccluded.AsDeferredJobArray(), radarCdfe = radarsCdfe, radarScanResultsCdfe = radarScanResultsCdfe, scannedEnemies = scannedEnemies.AsDeferredJobArray() }; resultsHandle = updateEnemiesJob.Schedule(JobHandle.CombineDependencies(enemiesJh1, enemiesJh2, resultsHandle)); finalHandles.Add(enemiesLineOfSightBodies.Dispose(resultsHandle)); finalHandles.Add(enemiesOccluded.Dispose(resultsHandle)); finalHandles.Add(scannedEnemies.Dispose(resultsHandle)); } finalHandles.Add(radarLayer.Dispose(resultsHandle)); Profiler.EndSample(); } Dependency = JobHandle.CombineDependencies(finalHandles); finalHandles.Dispose(); factionEntities.Dispose(); m_factionsCache.Clear(); Profiler.EndSample(); }
protected override void OnUpdate() { bool needPlayer = m_oldPlayerShipQuery.IsEmptyIgnoreFilter; SpawnQueues spawnQueues = default; if (sceneGlobalEntity.HasCollectionComponent <SpawnQueues>()) { spawnQueues = sceneGlobalEntity.GetCollectionComponent <SpawnQueues>(); } else { spawnQueues.playerQueue = new NativeQueue <Entity>(Allocator.Persistent); spawnQueues.aiQueue = new NativeQueue <Entity>(Allocator.Persistent); spawnQueues.newAiEntitiesToPrioritize = new NativeList <Entity>(Allocator.Persistent); spawnQueues.factionRanges = new NativeList <SpawnQueues.FactionRanges>(Allocator.Persistent); sceneGlobalEntity.AddCollectionComponent(spawnQueues); } Entities.WithStructuralChanges().WithAll <FactionTag>().ForEach((Entity entity, ref Faction faction) => { var factionFilter = new FactionMember { factionEntity = entity }; m_oldShipQuery.SetSharedComponentFilter(factionFilter); int unitsToSpawn = faction.maxFieldUnits - m_oldShipQuery.CalculateEntityCount(); unitsToSpawn = math.min(unitsToSpawn, faction.remainingReinforcements); if (needPlayer && faction.playerPrefab != Entity.Null) { var newPlayerShip = EntityManager.Instantiate(faction.playerPrefab); EntityManager.AddComponent <NewShipTag>(newPlayerShip); AddSharedComponentDataToLinkedGroup(newPlayerShip, factionFilter); if (faction.remainingReinforcements <= 0) { m_playersWithoutReinforcements.Add(newPlayerShip); } else { EntityManager.SetEnabled(newPlayerShip, false); unitsToSpawn--; faction.remainingReinforcements--; spawnQueues.playerQueue.Enqueue(newPlayerShip); } } if (unitsToSpawn > 0) { var newShipPrefab = EntityManager.Instantiate(faction.aiPrefab); EntityManager.AddComponent <NewShipTag>(newShipPrefab); AddSharedComponentDataToLinkedGroup(newShipPrefab, factionFilter); EntityManager.SetEnabled(newShipPrefab, false); var newEntities = EntityManager.Instantiate(newShipPrefab, unitsToSpawn, Allocator.TempJob); int start = spawnQueues.newAiEntitiesToPrioritize.Length; spawnQueues.newAiEntitiesToPrioritize.AddRange(newEntities); spawnQueues.factionRanges.Add(new SpawnQueues.FactionRanges { start = start, count = newEntities.Length, weight = faction.spawnWeightInverse / newEntities.Length }); newEntities.Dispose(); EntityManager.DestroyEntity(newShipPrefab); faction.remainingReinforcements -= unitsToSpawn; } m_oldShipQuery.ResetFilter(); }).Run(); EntityManager.RemoveComponent <NewShipTag>(m_newAiShipQuery); EntityManager.RemoveComponent <NewShipTag>(m_newPlayerShipQuery); foreach (var player in m_playersWithoutReinforcements) { if (!FindAndStealAiShip(player, spawnQueues)) { EntityManager.DestroyEntity(player); } } m_playersWithoutReinforcements.Clear(); }