/** * <summary> * Getting the closest object to avoide * </summary> */ public AvoiderChecker GetClosestMovingAvoidanceObject(Vector3 currentPosition, Vector3 preferredDirection) { AvoiderChecker closestObject = null; float closestDistance = 2000.0f; foreach (var objectToAvoid in objectsToAvoid) { if (objectToAvoid.movingObject == false) { continue; } if (ObjectIsBehindAvoider(preferredDirection, objectToAvoid, currentPosition)) { continue; } float distance = Vector3.Distance(currentPosition, objectToAvoid.transform.position); if (distance < closestDistance) { closestDistance = distance; closestObject = objectToAvoid; } } return(closestObject); }
/** * <summary> * Get preferred avoidance direction from one object * </summary> */ private Vector3 GetPreferredAvoidanceDirectionFromOneObject( AvoiderChecker objectToAvoid, Vector3 preferredDirection, Vector3 currentPosition) { // P - The object to avoid // D - Direction of line (unit length) // A - The current position of the moving object // X - base of the perpendicular line // // P // /| // / | // / v // A---X----->D Ray ray = new Ray(currentPosition, preferredDirection.normalized); Vector3 p = objectToAvoid.gameObject.transform.position; Vector3 a = currentPosition; Vector3 d = ray.direction; Vector3 x = a + (Vector3.Dot((p - a), d)) * d; Vector3 avoidanceVector = (x - p); ///It is important that we do not want the y-axis avoidanceVector.y = 0; return(avoidanceVector.normalized * GetAvoidanceVelocity(objectToAvoid, currentPosition, avoidanceVector)); }
void LookAtObjectToAvoid(AvoiderChecker objectToLookAt) { Vector3 lookDirection = (objectToLookAt.transform.position - headTransform.position); var newHeadRotation = Quaternion.LookRotation(lookDirection, Vector3.up); UpdateHeadRotationAngle(newHeadRotation); }
/** * <summary> * Checking if the object is behind the avoider. * </summary> */ private bool ObjectIsBehindAvoider(Vector3 preferredDirection, AvoiderChecker objectToAvoid, Vector3 currentPosition) { Vector3 vectorToObjectToAvoid = GetVectorToObjectToAvoid(objectToAvoid, currentPosition); Vector3 projectedVector = Vector3.Project(vectorToObjectToAvoid, preferredDirection); float errorMargin = 0.1f; bool isBehind = preferredDirection.magnitude + projectedVector.magnitude - errorMargin > (projectedVector + preferredDirection).magnitude; return(isBehind); }
/** * <summary> * This removes an object that should no longer be avoided. * </summary> */ public void RemoveObjectToAvoid(AvoiderChecker objectToRemove) { bool objectExist = objectsToAvoid.Contains(objectToRemove); if (!objectExist) { return; } objectsToAvoid.Remove(objectToRemove); }
/** * <summary> * This adds an object that should be avoided. * </summary> */ public void AddObjectToAvoid(AvoiderChecker newObjectToAvoid) { bool newObjectAlreadyAdded = objectsToAvoid.Contains(newObjectToAvoid); if (newObjectAlreadyAdded) { return; } objectsToAvoid.Add(newObjectToAvoid); }
/** * <summary> * Getting the avoindace velocity, also called avoidance weights * </summary> */ private float GetAvoidanceVelocity( AvoiderChecker objectToAvoid, Vector3 currentPosition, Vector3 avoidanceVector ) { currentPosition.y = 0; Vector3 objectToAvoidPosition = objectToAvoid.gameObject.transform.position; objectToAvoidPosition.y = 0; float avoiderRadius = objectToAvoid.detectRadius; float detectFactor = Math.Max(1 - ((Vector3.Distance(currentPosition, objectToAvoidPosition) - objectToAvoid.avoidRadius) / (objectToAvoid.detectRadius - objectToAvoid.avoidRadius)), 0.0f); float avoidFactor = Math.Max(1 - (avoidanceVector.magnitude / objectToAvoid.avoidRadius), 0.0f); return(avoidFactor * detectFactor); }
void UpdateHeadRotation() { if (this.avoiderComponent == null) { return; } AvoiderChecker closestObject = this.avoiderComponent.GetClosestMovingAvoidanceObject(transform.position, this.movement.preferredWalkingDirection); if (closestObject == null) { UpdateHeadRotationAngle(GetDirectionLookRotation()); return; } if (isShyNPC) { LookAwayFromObjectToAvoid(closestObject); } else { LookAtObjectToAvoid(closestObject); } }
/** * <summary> * Getting the vector from the current avoider to the object to avoid * </summary> */ private Vector3 GetVectorToObjectToAvoid(AvoiderChecker objectToAvoid, Vector3 currentPosition) { return(objectToAvoid.transform.position - currentPosition); }
void LookAwayFromObjectToAvoid(AvoiderChecker objectToLookAt) { UpdateHeadRotationAngle(GetDirectionLookRotation() * Quaternion.Euler(preferredLookAwayDirection)); }