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);
Beispiel #2
0
        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();
        }
Beispiel #4
0
        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();
        }