/** Called during either Update or FixedUpdate depending on if rigidbodies are used for movement or not */ protected override void MovementUpdateInternal (float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation) { // a = v/t, should probably expose as a variable float acceleration = maxSpeed / 0.4f; if (updatePosition) { // Get our current position. We read from transform.position as few times as possible as it is relatively slow // (at least compared to a local variable) simulatedPosition = tr.position; } if (updateRotation) simulatedRotation = tr.rotation; var currentPosition = simulatedPosition; // Update which point we are moving towards interpolator.MoveToCircleIntersection2D(currentPosition, pickNextWaypointDist, movementPlane); var dir = movementPlane.ToPlane(steeringTarget - currentPosition); // Calculate the distance to the end of the path float distanceToEnd = dir.magnitude + Mathf.Max(0, interpolator.remainingDistance); // Check if we have reached the target var prevTargetReached = reachedEndOfPath; reachedEndOfPath = distanceToEnd <= endReachedDistance && interpolator.valid; if (!prevTargetReached && reachedEndOfPath) OnTargetReached(); float slowdown; // Check if we have a valid path to follow and some other script has not stopped the character if (interpolator.valid && !isStopped) { // How fast to move depending on the distance to the destination. // Move slower as the character gets closer to the destination. // This is always a value between 0 and 1. slowdown = distanceToEnd < slowdownDistance ? Mathf.Sqrt(distanceToEnd / slowdownDistance) : 1; if (reachedEndOfPath && whenCloseToDestination == CloseToDestinationMode.Stop) { // Slow down as quickly as possible velocity2D -= Vector2.ClampMagnitude(velocity2D, acceleration * deltaTime); } else { velocity2D += MovementUtilities.CalculateAccelerationToReachPoint(dir, dir.normalized*maxSpeed, velocity2D, acceleration, maxSpeed) * deltaTime; } } else { slowdown = 1; // Slow down as quickly as possible velocity2D -= Vector2.ClampMagnitude(velocity2D, acceleration * deltaTime); } velocity2D = MovementUtilities.ClampVelocity(velocity2D, maxSpeed, slowdown, slowWhenNotFacingTarget, movementPlane.ToPlane(rotationIn2D ? tr.up : tr.forward)); ApplyGravity(deltaTime); if (rvoController != null && rvoController.enabled) { // Send a message to the RVOController that we want to move // with this velocity. In the next simulation step, this // velocity will be processed and it will be fed back to the // rvo controller and finally it will be used by this script // when calling the CalculateMovementDelta method below // Make sure that we don't move further than to the end point // of the path. If the RVO simulation FPS is low and we did // not do this, the agent might overshoot the target a lot. var rvoTarget = currentPosition + movementPlane.ToWorld(Vector2.ClampMagnitude(velocity2D, distanceToEnd), 0f); rvoController.SetTarget(rvoTarget, velocity2D.magnitude, maxSpeed); } // Set how much the agent wants to move during this frame var delta2D = lastDeltaPosition = CalculateDeltaToMoveThisFrame(movementPlane.ToPlane(currentPosition), distanceToEnd, deltaTime); nextPosition = currentPosition + movementPlane.ToWorld(delta2D, verticalVelocity * lastDeltaTime); CalculateNextRotation(slowdown, out nextRotation); }