예제 #1
0
        /// <summary>
        /// Predicts the time until nearest approach between this and another vehicle
        /// </summary>
        /// <returns>
        /// The nearest approach time.
        /// </returns>
        /// <param name='other'>
        /// Other vehicle to compare against
        /// </param>
        public float PredictNearestApproachTime(Vehicle2D other)
        {
            // imagine we are at the origin with no velocity,
            // compute the relative velocity of the other vehicle
            var otherVelocity = other.Velocity;
            var relVelocity   = otherVelocity - Velocity;
            var relSpeed      = relVelocity.magnitude;

            // for parallel paths, the vehicles will always be at the same distance,
            // so return 0 (aka "now") since "there is no time like the present"
            if (Mathf.Approximately(relSpeed, 0))
            {
                return(0);
            }

            // Now consider the path of the other vehicle in this relative
            // space, a line defined by the relative position and velocity.
            // The distance from the origin (our vehicle) to that line is
            // the nearest approach.

            // Take the unit tangent along the other vehicle's path
            var relTangent = relVelocity / relSpeed;

            // find distance from its path to origin (compute offset from
            // other to us, find length of projection onto path)
            var relPosition = Position - other.Position;
            var projection  = Vector2.Dot(relTangent, relPosition);

            return(projection / relSpeed);
        }
예제 #2
0
        /// <summary>
        /// Calculates if a vehicle is in the neighborhood of another
        /// </summary>
        /// <param name="other">
        /// Another vehicle to check against<see cref="Vehicle"/>
        /// </param>
        /// <param name="minDistance">
        /// Minimum distance <see cref="System.Single"/>
        /// </param>
        /// <param name="maxDistance">
        /// Maximum distance <see cref="System.Single"/>
        /// </param>
        /// <param name="cosMaxAngle">
        /// Cosine of the maximum angle between vehicles (for performance)<see cref="System.Single"/>
        /// </param>
        /// <returns>
        /// True if the other vehicle can be considered to our neighbor, or false if otherwise<see cref="System.Boolean"/>
        /// </returns>
        /// <remarks>Originally SteerLibrary.inBoidNeighborhood</remarks>
        public bool IsInNeighborhood(Vehicle2D other, float minDistance, float maxDistance, float cosMaxAngle)
        {
            var result = false;

            if (other != this)
            {
                var offset          = other.Position - Position;
                var distanceSquared = offset.sqrMagnitude;

                // definitely in neighborhood if inside minDistance sphere
                if (distanceSquared < (minDistance * minDistance))
                {
                    result = true;
                }
                else
                {
                    // definitely not in neighborhood if outside maxDistance sphere
                    if (distanceSquared <= (maxDistance * maxDistance))
                    {
                        // otherwise, test angular offset from forward axis
                        var unitOffset  = offset / Mathf.Sqrt(distanceSquared);
                        var forwardness = Vector2.Dot(Forward, unitOffset);
                        result = forwardness > cosMaxAngle;
                    }
                }
            }
            return(result);
        }
예제 #3
0
 /// <summary>
 /// Given the time until nearest approach (predictNearestApproachTime)
 /// determine position of each vehicle at that time, and the distance
 /// between them
 /// </summary>
 /// <returns>
 /// Distance between positions
 /// </returns>
 /// <param name='other'>
 /// Other vehicle to compare against
 /// </param>
 /// <param name='time'>
 /// Time to estimate.
 /// </param>
 /// <param name='ourPosition'>
 /// Our position.
 /// </param>
 /// <param name='hisPosition'>
 /// The other vehicle's position.
 /// </param>
 public float ComputeNearestApproachPositions(Vehicle2D other, float time,
                                              ref Vector2 ourPosition,
                                              ref Vector2 hisPosition)
 {
     return(ComputeNearestApproachPositions(other, time, ref ourPosition, ref hisPosition, Speed,
                                            Forward));
 }
예제 #4
0
 public override Vector2 CalculateNeighborContribution(Vehicle2D other)
 {
     // accumulate sum of forces leading us towards neighbor's positions
     var distance = other.Position - Vehicle.Position;
     var sqrMag = distance.sqrMagnitude;
     // Provide some contribution, but diminished by the distance to 
     // the vehicle.
     distance *= 1 / sqrMag;
     return distance;
 }
        public override Vector2 CalculateNeighborContribution(Vehicle2D other)
        {
            // accumulate sum of forces leading us towards neighbor's positions
            var distance = other.Position - Vehicle.Position;
            var sqrMag   = distance.sqrMagnitude;

            // Provide some contribution, but diminished by the distance to
            // the vehicle.
            distance *= 1 / sqrMag;
            return(distance);
        }
        public override Vector2 CalculateNeighborContribution(Vehicle2D other)
        {
            if (_guildMember != null && GuildMember.CachedGroups.ContainsKey(other.gameObject))
            {
                var otherGroup = GuildMember.CachedGroups[other.gameObject];
                if (otherGroup != _guildMember.Grouping)
                    return Vector2.zero;
            }

            // accumulate sum of neighbors' velocities
            return other.Velocity;
        }
예제 #7
0
        /// <summary>
        /// Given the time until nearest approach (predictNearestApproachTime)
        /// determine position of each vehicle at that time, and the distance
        /// between them
        /// </summary>
        /// <returns>
        /// Distance between positions
        /// </returns>
        /// <param name='other'>
        /// Other vehicle to compare against
        /// </param>
        /// <param name='time'>
        /// Time to estimate.
        /// </param>
        /// <param name='ourPosition'>
        /// Our position.
        /// </param>
        /// <param name='hisPosition'>
        /// The other vehicle's position.
        /// </param>
        /// <param name="ourSpeed">Our speed to use for the calculations</param>
        /// <param name='ourForward'>
        /// Forward vector to use instead of the vehicle's.
        /// </param>
        public float ComputeNearestApproachPositions(Vehicle2D other, float time,
                                                     ref Vector2 ourPosition,
                                                     ref Vector2 hisPosition,
                                                     float ourSpeed,
                                                     Vector2 ourForward)
        {
            var myTravel    = ourForward * ourSpeed * time;
            var otherTravel = other.Forward * other.Speed * time;

            //The casts are to make sure they are both the same even when changing from 2D to 3D.
            ourPosition = Position + myTravel;
            hisPosition = other.Position + otherTravel;

            return(Vector2.Distance(ourPosition, hisPosition));
        }
예제 #8
0
    public override Vector2 CalculateNeighborContribution(Vehicle2D other)
    {
        //if (_guildMember.Grouping != 0)
        {
            if (GuildMember.CachedGroups.ContainsKey(other.gameObject))
            {
                var otherGroup = GuildMember.CachedGroups[other.gameObject];
                if (//otherGroup != 0 && 
                    otherGroup != _guildMember.Grouping)
                    return Vector2.zero;
            }
        }

        // accumulate sum of forces leading us towards neighbor's positions
        var distance = other.Position - Vehicle.Position;
        var sqrMag = distance.sqrMagnitude;
        // Provide some contribution, but diminished by the distance to 
        // the vehicle.
        distance *= 1 / sqrMag;
        return distance;
    }
예제 #9
0
        public override Vector2 CalculateNeighborContribution(Vehicle2D other)
        {
            var steering = Vector2.zero;

            // add in steering contribution
            // (opposite of the offset direction, divided once by distance
            // to normalize, divided another time to get 1/d falloff)
            var offset       = other.Position - Vehicle.Position;
            var offsetSqrMag = offset.sqrMagnitude;

            steering = (offset / -offsetSqrMag);
            if (!Mathf.Approximately(_multiplierInsideComfortDistance, 1) && offsetSqrMag < _comfortDistanceSquared)
            {
                steering *= _multiplierInsideComfortDistance;
            }

            if (_vehicleRadiusImpact > 0)
            {
                steering *= (other.Radius + Vehicle.Radius) * _vehicleRadiusImpact;
            }

            return(steering);
        }
예제 #10
0
        public override Vector2 CalculateNeighborContribution(Vehicle2D other)
        {
            var steering = Vector2.zero;

            // add in steering contribution
            // (opposite of the offset direction, divided once by distance
            // to normalize, divided another time to get 1/d falloff)
            var offset = other.Position - Vehicle.Position;
            var offsetSqrMag = offset.sqrMagnitude;

            steering = (offset / -offsetSqrMag);
            if (!Mathf.Approximately(_multiplierInsideComfortDistance, 1) && offsetSqrMag < _comfortDistanceSquared)
            {
                steering *= _multiplierInsideComfortDistance;
            }

            if (_vehicleRadiusImpact > 0)
            {
                steering *= (other.Radius + Vehicle.Radius) * _vehicleRadiusImpact;
            }

            return steering;
        }
        /// <summary>
        /// Finds a vehicle's next intersection with a spherical obstacle
        /// </summary>
        /// <param name="vehicle">
        /// The vehicle to evaluate.
        /// </param>
        /// <param name="futureVehiclePosition">
        /// The position where we expect the vehicle to be soon
        /// </param>
        /// <param name="obstacle">
        /// A spherical obstacle to check against <see cref="DetectableObject"/>
        /// </param>
        /// <returns>
        /// A PathIntersection with the intersection details <see cref="PathIntersection"/>
        /// </returns>
        /// <remarks>We could probably spin out this function to an independent tool class</remarks>
        public static PathIntersection FindNextIntersectionWithSphere(Vehicle2D vehicle, Vector2 futureVehiclePosition,
            DetectableObject2D obstacle)
        {
            // this mainly follows http://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/

            var intersection = new PathIntersection(obstacle);

            var combinedRadius = vehicle.Radius + obstacle.Radius;
            var movement = futureVehiclePosition - vehicle.Position;
            var direction = movement.normalized;

            var vehicleToObstacle = obstacle.Position - vehicle.Position;

            // this is the length of vehicleToObstacle projected onto direction
            var projectionLength = Vector2.Dot(direction, vehicleToObstacle);

            // if the projected obstacle center lies further away than our movement + both radius, we're not going to collide
            if (projectionLength > movement.magnitude + combinedRadius)
            {
                //print("no collision - 1");
                return intersection;
            }

            // the foot of the perpendicular
            var projectedObstacleCenter = vehicle.Position + projectionLength * direction;

            // distance of the obstacle to the pathe the vehicle is going to take
            var obstacleDistanceToPath = (obstacle.Position - projectedObstacleCenter).magnitude;
            //print("obstacleDistanceToPath: " + obstacleDistanceToPath);

            // if the obstacle is further away from the movement, than both radius, there's no collision
            if (obstacleDistanceToPath > combinedRadius)
            {
                //print("no collision - 2");
                return intersection;
            }

            // use pythagorean theorem to calculate distance out of the sphere (if you do it 2D, the line through the circle would be a chord and we need half of its length)
            var halfChord = Mathf.Sqrt(combinedRadius * combinedRadius + obstacleDistanceToPath * obstacleDistanceToPath);

            // if the projected obstacle center lies opposite to the movement direction (aka "behind")
            if (projectionLength < 0)
            {
                // behind and further away than both radius -> no collision (we already passed)
                if (vehicleToObstacle.magnitude > combinedRadius)
                    return intersection;

                var intersectionPoint = projectedObstacleCenter - direction * halfChord;
                intersection.Intersect = true;
                intersection.Distance = (intersectionPoint - vehicle.Position).magnitude;
                return intersection;
            }

            // calculate both intersection points
            var intersectionPoint1 = projectedObstacleCenter - direction * halfChord;
            var intersectionPoint2 = projectedObstacleCenter + direction * halfChord;

            // pick the closest one
            var intersectionPoint1Distance = (intersectionPoint1 - vehicle.Position).magnitude;
            var intersectionPoint2Distance = (intersectionPoint2 - vehicle.Position).magnitude;

            intersection.Intersect = true;
            intersection.Distance = Mathf.Min(intersectionPoint1Distance, intersectionPoint2Distance);

            return intersection;
        }
예제 #12
0
 public abstract Vector2 CalculateNeighborContribution(Vehicle2D other);
예제 #13
0
        /// <summary>
        /// Calculates if a vehicle is in the neighborhood of another
        /// </summary>
        /// <param name="other">
        /// Another vehicle to check against<see cref="Vehicle"/>
        /// </param>
        /// <param name="minDistance">
        /// Minimum distance <see cref="System.Single"/>
        /// </param>
        /// <param name="maxDistance">
        /// Maximum distance <see cref="System.Single"/>
        /// </param>
        /// <param name="cosMaxAngle">
        /// Cosine of the maximum angle between vehicles (for performance)<see cref="System.Single"/>
        /// </param>
        /// <returns>
        /// True if the other vehicle can be considered to our neighbor, or false if otherwise<see cref="System.Boolean"/>
        /// </returns>
        /// <remarks>Originally SteerLibrary.inBoidNeighborhood</remarks>
        public bool IsInNeighborhood(Vehicle2D other, float minDistance, float maxDistance, float cosMaxAngle)
        {
            var result = false;
            if (other != this)
            {
                var offset = other.Position - Position;
                var distanceSquared = offset.sqrMagnitude;

                // definitely in neighborhood if inside minDistance sphere
                if (distanceSquared < (minDistance * minDistance))
                {
                    result = true;
                }
                else
                {
                    // definitely not in neighborhood if outside maxDistance sphere
                    if (distanceSquared <= (maxDistance * maxDistance))
                    {
                        // otherwise, test angular offset from forward axis
                        var unitOffset = offset / Mathf.Sqrt(distanceSquared);
                        var forwardness = Vector2.Dot(Forward, unitOffset);
                        result = forwardness > cosMaxAngle;
                    }
                }
            }
            return result;
        }
예제 #14
0
 public override Vector2 CalculateNeighborContribution(Vehicle2D other)
 {
     // accumulate sum of neighbor's heading
     return other.Forward;
 }
예제 #15
0
 public override Vector2 CalculateNeighborContribution(Vehicle2D other)
 {
     // accumulate sum of neighbor's heading
     return(other.Forward);
 }
예제 #16
0
 /// <summary>
 /// Returns the distance from this vehicle to another
 /// </summary>
 /// <returns>
 /// The distance between both vehicles' positions. If negative, they are overlapping.
 /// </returns>
 /// <param name='other'>
 /// Vehicle to compare against.
 /// </param>
 public float DistanceFromPerimeter(Vehicle2D other)  {
     var diff = Position - other.Position;
     return diff.magnitude - Radius - other.Radius;
 }
예제 #17
0
 protected virtual void Awake()
 {
     _vehicle        = GetComponent <Vehicle2D>();
     ReportedArrival = true; // Default to true to avoid unnecessary notifications
 }
예제 #18
0
 protected virtual void Awake()
 {
     _vehicle = GetComponent<Vehicle2D>();
     ReportedArrival = true; // Default to true to avoid unnecessary notifications
 }
예제 #19
0
        /// <summary>
        /// Predicts the time until nearest approach between this and another vehicle
        /// </summary>
        /// <returns>
        /// The nearest approach time.
        /// </returns>
        /// <param name='other'>
        /// Other vehicle to compare against
        /// </param>
        public float PredictNearestApproachTime(Vehicle2D other)  {
            // imagine we are at the origin with no velocity,
            // compute the relative velocity of the other vehicle
            var otherVelocity = other.Velocity;
            var relVelocity = otherVelocity - Velocity;
            var relSpeed = relVelocity.magnitude;

            // for parallel paths, the vehicles will always be at the same distance,
            // so return 0 (aka "now") since "there is no time like the present"
            if (Mathf.Approximately(relSpeed, 0))
            {
                return 0;
            }

            // Now consider the path of the other vehicle in this relative
            // space, a line defined by the relative position and velocity.
            // The distance from the origin (our vehicle) to that line is
            // the nearest approach.

            // Take the unit tangent along the other vehicle's path
            var relTangent = relVelocity / relSpeed;

            // find distance from its path to origin (compute offset from
            // other to us, find length of projection onto path)
            var relPosition = Position - other.Position;
            var projection = Vector2.Dot(relTangent, relPosition);

            return projection / relSpeed;
        }
예제 #20
0
        /// <summary>
        /// Returns the distance from this vehicle to another
        /// </summary>
        /// <returns>
        /// The distance between both vehicles' positions. If negative, they are overlapping.
        /// </returns>
        /// <param name='other'>
        /// Vehicle to compare against.
        /// </param>
        public float DistanceFromPerimeter(Vehicle2D other)
        {
            var diff = Position - other.Position;

            return(diff.magnitude - Radius - other.Radius);
        }
예제 #21
0
 /// <summary>
 /// Given the time until nearest approach (predictNearestApproachTime)
 /// determine position of each vehicle at that time, and the distance
 /// between them
 /// </summary>
 /// <returns>
 /// Distance between positions
 /// </returns>
 /// <param name='other'>
 /// Other vehicle to compare against
 /// </param>
 /// <param name='time'>
 /// Time to estimate.
 /// </param>
 /// <param name='ourPosition'>
 /// Our position.
 /// </param>
 /// <param name='hisPosition'>
 /// The other vehicle's position.
 /// </param>
 public float ComputeNearestApproachPositions(Vehicle2D other, float time,
     ref Vector2 ourPosition,
     ref Vector2 hisPosition)
 {
     return ComputeNearestApproachPositions(other, time, ref ourPosition, ref hisPosition, Speed,
         Forward);
 }
        /// <summary>
        /// Finds a vehicle's next intersection with a spherical obstacle
        /// </summary>
        /// <param name="vehicle">
        /// The vehicle to evaluate.
        /// </param>
        /// <param name="futureVehiclePosition">
        /// The position where we expect the vehicle to be soon
        /// </param>
        /// <param name="obstacle">
        /// A spherical obstacle to check against <see cref="DetectableObject"/>
        /// </param>
        /// <returns>
        /// A PathIntersection with the intersection details <see cref="PathIntersection"/>
        /// </returns>
        /// <remarks>We could probably spin out this function to an independent tool class</remarks>
        public static PathIntersection FindNextIntersectionWithSphere(Vehicle2D vehicle, Vector2 futureVehiclePosition,
                                                                      DetectableObject2D obstacle)
        {
            // this mainly follows http://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/

            var intersection = new PathIntersection(obstacle);

            var combinedRadius = vehicle.Radius + obstacle.Radius;
            var movement       = futureVehiclePosition - vehicle.Position;
            var direction      = movement.normalized;

            var vehicleToObstacle = obstacle.Position - vehicle.Position;

            // this is the length of vehicleToObstacle projected onto direction
            var projectionLength = Vector2.Dot(direction, vehicleToObstacle);

            // if the projected obstacle center lies further away than our movement + both radius, we're not going to collide
            if (projectionLength > movement.magnitude + combinedRadius)
            {
                //print("no collision - 1");
                return(intersection);
            }

            // the foot of the perpendicular
            var projectedObstacleCenter = vehicle.Position + projectionLength * direction;

            // distance of the obstacle to the pathe the vehicle is going to take
            var obstacleDistanceToPath = (obstacle.Position - projectedObstacleCenter).magnitude;

            //print("obstacleDistanceToPath: " + obstacleDistanceToPath);

            // if the obstacle is further away from the movement, than both radius, there's no collision
            if (obstacleDistanceToPath > combinedRadius)
            {
                //print("no collision - 2");
                return(intersection);
            }

            // use pythagorean theorem to calculate distance out of the sphere (if you do it 2D, the line through the circle would be a chord and we need half of its length)
            var halfChord = Mathf.Sqrt(combinedRadius * combinedRadius + obstacleDistanceToPath * obstacleDistanceToPath);

            // if the projected obstacle center lies opposite to the movement direction (aka "behind")
            if (projectionLength < 0)
            {
                // behind and further away than both radius -> no collision (we already passed)
                if (vehicleToObstacle.magnitude > combinedRadius)
                {
                    return(intersection);
                }

                var intersectionPoint = projectedObstacleCenter - direction * halfChord;
                intersection.Intersect = true;
                intersection.Distance  = (intersectionPoint - vehicle.Position).magnitude;
                return(intersection);
            }

            // calculate both intersection points
            var intersectionPoint1 = projectedObstacleCenter - direction * halfChord;
            var intersectionPoint2 = projectedObstacleCenter + direction * halfChord;

            // pick the closest one
            var intersectionPoint1Distance = (intersectionPoint1 - vehicle.Position).magnitude;
            var intersectionPoint2Distance = (intersectionPoint2 - vehicle.Position).magnitude;

            intersection.Intersect = true;
            intersection.Distance  = Mathf.Min(intersectionPoint1Distance, intersectionPoint2Distance);

            return(intersection);
        }
 public override Vector2 CalculateNeighborContribution(Vehicle2D other)
 {
     // accumulate sum of neighbors' velocities
     return(other.Velocity);
 }
예제 #24
0
        /// <summary>
        /// Given the time until nearest approach (predictNearestApproachTime)
        /// determine position of each vehicle at that time, and the distance
        /// between them
        /// </summary>
        /// <returns>
        /// Distance between positions
        /// </returns>
        /// <param name='other'>
        /// Other vehicle to compare against
        /// </param>
        /// <param name='time'>
        /// Time to estimate.
        /// </param>
        /// <param name='ourPosition'>
        /// Our position.
        /// </param>
        /// <param name='hisPosition'>
        /// The other vehicle's position.
        /// </param>
        /// <param name="ourSpeed">Our speed to use for the calculations</param>
        /// <param name='ourForward'>
        /// Forward vector to use instead of the vehicle's.
        /// </param>
        public float ComputeNearestApproachPositions(Vehicle2D other, float time,
            ref Vector2 ourPosition,
            ref Vector2 hisPosition,
            float ourSpeed,
            Vector2 ourForward)
        {
            var myTravel = ourForward * ourSpeed * time;
            var otherTravel = other.Forward * other.Speed * time;

            //The casts are to make sure they are both the same even when changing from 2D to 3D.
            ourPosition = Position + myTravel;
            hisPosition = other.Position + otherTravel;

            return Vector2.Distance(ourPosition, hisPosition);
        }
 public abstract Vector2 CalculateNeighborContribution(Vehicle2D other);
예제 #26
0
 public override Vector2 CalculateNeighborContribution(Vehicle2D other)
 {
     // accumulate sum of neighbors' velocities
     return other.Velocity;
 }