public override Vector3 CalculateNeighborContribution(Vehicle 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 Vector3 CalculateNeighborContribution(Vehicle other)
        {
            var steering = Vector3.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;
        }
 public override Vector3 CalculateNeighborContribution(Vehicle other)
 {
     // accumulate sum of neighbors' velocities
     return other.Velocity;
 }
        /// <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(Vehicle vehicle, Vector3 futureVehiclePosition,
            DetectableObject 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 = Vector3.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;
        }
Beispiel #5
0
 public abstract Vector3 CalculateNeighborContribution(Vehicle other);
 public override Vector3 CalculateNeighborContribution(Vehicle other)
 {
     // accumulate sum of neighbor's heading
     return other.Transform.forward;
 }
Beispiel #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(Vehicle other, float time,
            ref Vector3 ourPosition,
            ref Vector3 hisPosition,
            float ourSpeed,
            Vector3 ourForward)
        {
            var myTravel = ourForward * ourSpeed * time;
            var otherTravel = other.Transform.forward * other.Speed * time;

            ourPosition = Position + myTravel;
            hisPosition = other.Position + otherTravel;

            return Vector3.Distance(ourPosition, hisPosition);
        }
Beispiel #8
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(Vehicle other, float time,
     ref Vector3 ourPosition,
     ref Vector3 hisPosition)
 {
     return ComputeNearestApproachPositions(other, time, ref ourPosition, ref hisPosition, Speed,
         Transform.forward);
 }
Beispiel #9
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(Vehicle 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 = Vector3.Dot(relTangent, relPosition);

            return projection / relSpeed;
        }
Beispiel #10
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(Vehicle other)
 {
     var diff = Position - other.Position;
     return diff.magnitude - Radius - other.Radius;
 }
Beispiel #11
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(Vehicle 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 = Vector3.Dot(Transform.forward, unitOffset);
                        result = forwardness > cosMaxAngle;
                    }
                }
            }
            return result;
        }
Beispiel #12
0
 protected virtual void Awake()
 {
     _vehicle = GetComponent<Vehicle>();
     ReportedArrival = true; // Default to true to avoid unnecessary notifications
 }