Esempio n. 1
0
        /// <summary>
        /// Handles the starship's targeting.
        /// </summary>
        protected override void OnUpdate()
        {
            // Note that we need to pass the quadrant system structure to WithReadOnly(). This is because other systems are
            // reading from it in parallel and we need to ensure the safety system that we will not modify the memory.
            var quadrantHashMap = QuadrantSystem.QuadrantHashMap;

            Entities.WithReadOnly(quadrantHashMap).WithAll <SpaceshipTag>().ForEach(
                (Entity entity, ref TargetingComponent target, in Translation pos, in TeamComponent team,
                 in BoidComponent boid) => {
                var hashMapKey = QuadrantSystem.HashKeyFromPosition(pos.Value);

                // Search neighboring quadrants if the currently locked target is still in range,
                // or find a new closest enemy target
                var minDistance    = float.MaxValue;
                var closestEntity  = target.TargetEntity;
                var closestPos     = target.TargetPosition;
                var newTargetFound = false;
                if (SearchQuadrantNeighbors(in quadrantHashMap, hashMapKey, entity, target.TargetingRadius,
                                            pos.Value, team.Team, target.TargetLocked, target.TargetEntity, ref minDistance,
                                            ref closestEntity, ref closestPos, ref newTargetFound))
                {
                    return;     // Currently locked target still in range
                }

                if (newTargetFound)
                {
                    target.TargetPosition = closestPos;
                    target.TargetEntity   = closestEntity;
                    target.TargetLocked   = true;
                }
                else
                {
                    target.TargetLocked = false;
                }
            }).ScheduleParallel();
Esempio n. 2
0
        /// <summary>
        /// Handles flocking simulation.
        /// </summary>
        protected override void OnUpdate()
        {
            var deltaTime = Time.DeltaTime;

            // Note that we need to pass the quadrant system structure to WithReadOnly(). This is because other systems are
            // reading from it in parallel and we need to ensure the safety system that we will not modify the memory.
            var quadrantHashMap = QuadrantSystem.QuadrantHashMap;

            // Query for all entities with BoidObstacle tag component
            var allObstacles = GetEntityQuery(ComponentType.ReadOnly <BoidObstacle>()).ToEntityArray(Allocator.TempJob);

            Entities.WithReadOnly(quadrantHashMap).WithReadOnly(allObstacles).WithAll <SpaceshipTag>().ForEach(
                (Entity entity, ref MovementComponent movement, in BoidComponent boid, in Translation pos,
                 in TargetingComponent target) => {
                var neighborCnt   = 0;
                var cohesionPos   = float3.zero;   // For average position in neighborhood
                var alignmentVec  = float3.zero;   // For average alignment vector
                var separationVec = float3.zero;   // For average separation vector

                // Get all translation components (will be needed for the obstacle positions)
                var allTranslations = GetComponentDataFromEntity <Translation>(true);

                // Search neighboring quadrants and update aggregate steering data
                var hashMapKey = QuadrantSystem.HashKeyFromPosition(pos.Value);
                SearchQuadrantNeighbors(in quadrantHashMap, hashMapKey, entity, boid.CellRadius, pos.Value,
                                        ref neighborCnt, ref cohesionPos, ref alignmentVec, ref separationVec);

                // Average steering data
                if (neighborCnt > 0)
                {
                    separationVec /= neighborCnt;
                    cohesionPos   /= neighborCnt;
                    alignmentVec  /= neighborCnt;
                }
                else
                {
                    // apply no steering
                    cohesionPos   = pos.Value;
                    alignmentVec  = movement.Heading;
                    separationVec = movement.Heading;
                }

                // Compute obstacle avoidance
                var avoidanceHeading = float3.zero;
                var avoidObstacle    = false;  // if the boid should avoid obstacle instead of normal steering
                for (var i = 0; i < allObstacles.Length; i++)
                {
                    var otherPos = allTranslations[allObstacles[i]];     // Obstacle position

                    var distance = Vector3.Distance(pos.Value, otherPos.Value);
                    if (distance >= boid.ObstacleAversionDistance)
                    {
                        continue;                                                // This obstacle is not close
                    }
                    avoidObstacle        = true;
                    var obstacleSteering = pos.Value - otherPos.Value;
                    if (obstacleSteering.Equals(float3.zero))
                    {
                        obstacleSteering = movement.Heading;
                    }
                    obstacleSteering = math.normalizesafe(obstacleSteering);

                    avoidanceHeading = otherPos.Value + obstacleSteering * boid.ObstacleAversionDistance -
                                       pos.Value;
                    break;     // We have found an obstacle to avoid
                }

                // Check if we are in pursuit and compute pursuit steering
                var pursuitSteering = float3.zero;
                if (target.TargetLocked)
                {
                    pursuitSteering = math.normalizesafe(target.TargetPosition - pos.Value) * boid.PursuitWeight;
                }

                // Combine all steering factors and decide which one to use
                var targetSteering     = math.normalizesafe(movement.Target - pos.Value) * boid.TargetWeight;
                var alignmentSteering  = math.normalizesafe(alignmentVec) * boid.AlignmentWeight;
                var cohesionSteering   = math.normalizesafe(cohesionPos - pos.Value) * boid.CohesionWeight;
                var separationSteering = math.normalizesafe(separationVec) * boid.SeparationWeight;
                var normalHeading      = math.normalizesafe(targetSteering + alignmentSteering + cohesionSteering +
                                                            separationSteering + pursuitSteering);

                var targetHeading = avoidObstacle ? avoidanceHeading : normalHeading;

                // Setting a new heading (shifted towards target heading)
                movement.Heading = math.normalizesafe(movement.Heading +
                                                      deltaTime * boid.SteeringSpeed *
                                                      (targetHeading - movement.Heading));
            }).ScheduleParallel();