/// <summary> /// Must be called when a detectable object is disabled to remove it from the list of known objects /// </summary> /// <param name="obj">Detectable object</param> /// <returns>True if the call to Remove succeeded</returns> public static bool RemoveDetectableObject2D(DetectableObject2D obj) { return(_knownDetectableObjects.Remove(obj.Collider.GetInstanceID())); }
public PathIntersection(DetectableObject2D obstacle) { Obstacle = obstacle; Intersect = false; Distance = float.MaxValue; }
/// <summary> /// Must be called when a detectable object is enabled so they can be easily identified /// </summary> /// <param name="obj">Detectable object</param> public static void AddDetectableObject2D(DetectableObject2D obj) { _knownDetectableObjects[obj.Collider.GetInstanceID()] = obj; }
/// <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; }
/// <summary> /// Must be called when a detectable object is disabled to remove it from the list of known objects /// </summary> /// <param name="obj">Detectable object</param> /// <returns>True if the call to Remove succeeded</returns> public static bool RemoveDetectableObject2D(DetectableObject2D obj) { return _knownDetectableObjects.Remove(obj.Collider.GetInstanceID()); }
/// <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); }