/* A seek steering behavior. Will return the steering for the current game object to seek a given position */ public Vector3 seek(Vector3 targetPosition, float maxSeekAccel) { //Get the direction Vector3 acceleration = rb.convertVector(targetPosition - transform.position); acceleration.Normalize(); //Accelerate to the target acceleration *= maxSeekAccel; return(acceleration); }
/* Finds the param for the closest point on the segment vw given the point p */ private float getParamForSegment(Vector3 p, Vector3 v, Vector3 w, MovementAIRigidbody rb) { Vector3 vw = w - v; vw = rb.convertVector(vw); float l2 = Vector3.Dot(vw, vw); if (l2 == 0) { return(0); } float t = Vector3.Dot(p - v, vw) / l2; if (t < 0) { t = 0; } else if (t > 1) { t = 1; } /* Multiple by (v - w).magnitude instead of Sqrt(l2) because we want the magnitude of the full 3D line segment */ return(t * (v - w).magnitude); }
/// <summary> /// Will return true if the character is at the end of the given path /// </summary> public bool isAtEndOfPath(LinePath path) { // If the path has only one node then just check the distance to that node if (path.Length == 1) { Vector3 endPos = rb.convertVector(path[0]); return(Vector3.Distance(rb.position, endPos) < stopRadius); } // Else see if the character is at the end of the path else { Vector3 finalDestination; /* Get the param for the closest position point on the path given the character's position */ float param = path.getParam(transform.position, rb); return(isAtEndOfPath(path, param, out finalDestination)); } }
public Vector3 getSteering(ICollection <MovementAIRigidbody> targets) { Vector3 acceleration = Vector3.zero; foreach (MovementAIRigidbody r in targets) { /* Get the direction and distance from the target */ Vector3 direction = rb.colliderPosition - r.colliderPosition; float dist = direction.magnitude; if (dist < maxSepDist) { /* Calculate the separation strength (can be changed to use inverse square law rather than linear) */ var strength = sepMaxAcceleration * (maxSepDist - dist) / (maxSepDist - rb.radius - r.radius); /* Added separation acceleration to the existing steering */ direction = rb.convertVector(direction); direction.Normalize(); acceleration += direction * strength; } } return(acceleration); }
public Vector3 getSteering(ICollection <MovementAIRigidbody> targets) { Vector3 acceleration = Vector3.zero; /* 1. Find the target that the character will collide with first */ /* The first collision time */ float shortestTime = float.PositiveInfinity; /* The first target that will collide and other data that * we will need and can avoid recalculating */ MovementAIRigidbody firstTarget = null; float firstMinSeparation = 0, firstDistance = 0, firstRadius = 0; Vector3 firstRelativePos = Vector3.zero, firstRelativeVel = Vector3.zero; foreach (MovementAIRigidbody r in targets) { /* Calculate the time to collision */ Vector3 relativePos = rb.colliderPosition - r.colliderPosition; Vector3 relativeVel = rb.realVelocity - r.realVelocity; float distance = relativePos.magnitude; float relativeSpeed = relativeVel.magnitude; if (relativeSpeed == 0) { continue; } float timeToCollision = -1 * Vector3.Dot(relativePos, relativeVel) / (relativeSpeed * relativeSpeed); /* Check if they will collide at all */ Vector3 separation = relativePos + relativeVel * timeToCollision; float minSeparation = separation.magnitude; if (minSeparation > rb.radius + r.radius + distanceBetween) { continue; } /* Check if its the shortest */ if (timeToCollision > 0 && timeToCollision < shortestTime) { shortestTime = timeToCollision; firstTarget = r; firstMinSeparation = minSeparation; firstDistance = distance; firstRelativePos = relativePos; firstRelativeVel = relativeVel; firstRadius = r.radius; } } /* 2. Calculate the steering */ /* If we have no target then exit */ if (firstTarget == null) { return(acceleration); } /* If we are going to collide with no separation or if we are already colliding then * steer based on current position */ if (firstMinSeparation <= 0 || firstDistance < rb.radius + firstRadius + distanceBetween) { acceleration = rb.colliderPosition - firstTarget.colliderPosition; } /* Else calculate the future relative position */ else { acceleration = firstRelativePos + firstRelativeVel * shortestTime; } /* Avoid the target */ acceleration = rb.convertVector(acceleration); acceleration.Normalize(); acceleration *= maxAcceleration; return(acceleration); }