/// <summary> /// Tells the radar to no longer ignore the detectable object when filtering the vehicles or objects detected /// </summary> /// <param name="o"> /// An object to remove from the ignore list<see cref="DetectableObject"/> /// </param> /// <returns>The radar</returns> public Radar DontIgnore(DetectableObject o) { if (_ignoredObjects.Contains(o)) { _ignoredObjects.Remove(o); } return(this); }
/// <summary> /// Tells the radar to ignore the detectable object when filtering the vehicles or objects detected /// </summary> /// <param name="o"> /// An object to be ignored<see cref="DetectableObject"/> /// </param> /// <returns>The radar</returns> public Radar Ignore(DetectableObject o) { if (o != null) { _ignoredObjects.Add(o); } return(this); }
/// <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 RemoveDetectableObject(DetectableObject obj) { return(_knownDetectableObjects.Remove(obj.Collider.GetInstanceID())); }
/// <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 AddDetectableObject(DetectableObject obj) { _knownDetectableObjects[obj.Collider.GetInstanceID()] = obj; }
protected override Vector3 CalculateForce() { //---added by Rose--- potential_quarry = GameObject.FindGameObjectsWithTag("humanCreature"); GameObject nearest = null; float nearest_dist = 100f; foreach (GameObject q in potential_quarry){ float difference = Vector3.Distance(q.transform.position, transform.position); if (difference < nearest_dist) { nearest = q; nearest_dist = difference; } } if (nearest != null) { _quarry = nearest.GetComponent<DetectableObject> (); } else { Debug.Log ("nearest human creature is null"); } // _quarry = GameObject.FindGameObjectWithTag("humanCreature").GetComponent<DetectableObject>(); if (_quarry == null) { //---added by Rose--- Debug.Log ("QUARRY IS NULL"); //-----end----------- enabled = false; return Vector3.zero; } else { Debug.Log ("HUMAN CREATURE QUARRY FOUND: " + _quarry.gameObject.name); } //-----end----------- var force = Vector3.zero; var offset = _quarry.Position - Vehicle.Position; var distance = offset.magnitude; var radius = Vehicle.Radius + _quarry.Radius + _acceptableDistance; if (!(distance > radius)) return force; var unitOffset = offset / distance; // how parallel are the paths of "this" and the quarry // (1 means parallel, 0 is pependicular, -1 is anti-parallel) var parallelness = Vector3.Dot(transform.forward, _quarry.transform.forward); // how "forward" is the direction to the quarry // (1 means dead ahead, 0 is directly to the side, -1 is straight back) var forwardness = Vector3.Dot(transform.forward, unitOffset); var directTravelTime = distance / Vehicle.Speed; // While we could parametrize this value, if we care about forward/backwards // these values are appropriate enough. var f = OpenSteerUtility.IntervalComparison(forwardness, -0.707f, 0.707f); var p = OpenSteerUtility.IntervalComparison(parallelness, -0.707f, 0.707f); float timeFactor = 0; // to be filled in below // Break the pursuit into nine cases, the cross product of the // quarry being [ahead, aside, or behind] us and heading // [parallel, perpendicular, or anti-parallel] to us. switch (f) { case +1: switch (p) { case +1: // ahead, parallel timeFactor = 4; break; case 0: // ahead, perpendicular timeFactor = 1.8f; break; case -1: // ahead, anti-parallel timeFactor = 0.85f; break; } break; case 0: switch (p) { case +1: // aside, parallel timeFactor = 1; break; case 0: // aside, perpendicular timeFactor = 0.8f; break; case -1: // aside, anti-parallel timeFactor = 4; break; } break; case -1: switch (p) { case +1: // behind, parallel timeFactor = 0.5f; break; case 0: // behind, perpendicular timeFactor = 2; break; case -1: // behind, anti-parallel timeFactor = 2; break; } break; } // estimated time until intercept of quarry var et = directTravelTime * timeFactor; var etl = (et > _maxPredictionTime) ? _maxPredictionTime : et; // estimated position of quarry at intercept var target = _quarry.PredictFuturePosition(etl); force = Vehicle.GetSeekVector(target, _slowDownOnApproach); #if ANNOTATE_PURSUIT Debug.DrawRay(Vehicle.Position, force, Color.blue); Debug.DrawLine(Quarry.Position, target, Color.cyan); Debug.DrawRay(target, Vector3.up * 4, Color.cyan); #endif return force; }
public PathIntersection(DetectableObject obstacle) { Obstacle = obstacle; Intersect = false; Distance = float.MaxValue; }
/// <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; }
/// <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 RemoveDetectableObject(DetectableObject obj) { return _knownDetectableObjects.Remove(obj.Collider.GetInstanceID()); }
/// <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 AddDetectableObject(DetectableObject obj) { _knownDetectableObjects[obj.Collider.GetInstanceID()] = obj; }
public PathIntersection(DetectableObject obstacle) { Obstacle = obstacle; Intersect = false; Distance = float.MaxValue; }
/// <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); }