Exemple #1
0
        /// <summary>Called during either Update or FixedUpdate depending on if rigidbodies are used for movement or not</summary>
        protected override void MovementUpdateInternal(float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation)
        {
            float currentAcceleration = maxAcceleration;

            // If negative, calculate the acceleration from the max speed
            if (currentAcceleration < 0)
            {
                currentAcceleration *= -maxSpeed;
            }

            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);

            currentDir = dir;

            // 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;

            // Normalized direction of where the agent is looking
            var forwards = movementPlane.ToPlane(simulatedRotation * (orientation == OrientationMode.YAxisForward ? Vector3.up : Vector3.forward));

            // 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, currentAcceleration * deltaTime);
                }
                else
                {
                    velocity2D += MovementUtilities.CalculateAccelerationToReachPoint(dir, dir.normalized * maxSpeed, velocity2D, currentAcceleration, rotationSpeed, maxSpeed, forwards) * deltaTime;
                }
            }
            else
            {
                slowdown = 1;
                // Slow down as quickly as possible
                velocity2D -= Vector2.ClampMagnitude(velocity2D, currentAcceleration * deltaTime);
            }

            velocity2D = MovementUtilities.ClampVelocity(velocity2D, maxSpeed, slowdown, slowWhenNotFacingTarget && enableRotation, forwards);

            ApplyGravity(deltaTime);


            // 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);
        }
Exemple #2
0
 /// <summary>Calculates how far to move during a single frame</summary>
 protected Vector2 CalculateDeltaToMoveThisFrame(Vector2 position, float distanceToEndOfPath, float deltaTime)
 {
     // Direction and distance to move during this frame
     return(Vector2.ClampMagnitude(velocity2D * deltaTime, distanceToEndOfPath));
 }
		/** 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);
		}
Exemple #4
0
        /// <summary>Called during either Update or FixedUpdate depending on if rigidbodies are used for movement or not</summary>
        protected override void MovementUpdateInternal(float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation)
        {
            float currentAcceleration = maxAcceleration;

            // If negative, calculate the acceleration from the max speed
            if (currentAcceleration < 0)
            {
                currentAcceleration *= -maxSpeed;
            }

            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 speedLimitFactor;

            // Normalized direction of where the agent is looking
            var forwards = movementPlane.ToPlane(simulatedRotation * (orientation == OrientationMode.YAxisForward ? Vector3.up : Vector3.forward));

            // Check if we have a valid path to follow and some other script has not stopped the character
            bool stopped = isStopped || (reachedEndOfPath && whenCloseToDestination == CloseToDestinationMode.Stop);

            if (rvoController != null)
            {
                rvoDensityBehavior.Update(reachedDestination, ref stopped, ref rvoController.priorityMultiplier, ref rvoController.flowFollowingStrength);
            }

            if (interpolator.valid && !stopped)
            {
                // 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.
                speedLimitFactor = distanceToEnd < slowdownDistance?Mathf.Sqrt(distanceToEnd / slowdownDistance) : 1;

                velocity2D += MovementUtilities.CalculateAccelerationToReachPoint(dir, dir.normalized * maxSpeed, velocity2D, currentAcceleration, rotationSpeed, maxSpeed, forwards) * deltaTime;
            }
            else
            {
                // Slow down as quickly as possible
                velocity2D -= Vector2.ClampMagnitude(velocity2D, currentAcceleration * deltaTime);
                // We are already slowing down as quickly as possible. Avoid limiting the speed in other ways.
                speedLimitFactor = 1;
            }

            velocity2D = MovementUtilities.ClampVelocity(velocity2D, maxSpeed, speedLimitFactor, slowWhenNotFacingTarget && enableRotation, preventMovingBackwards, forwards);

            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(currentPosition, distanceToEnd, deltaTime);

            nextPosition = currentPosition + movementPlane.ToWorld(delta2D, verticalVelocity * deltaTime);
            CalculateNextRotation(speedLimitFactor, out nextRotation);
        }
Exemple #5
0
        void TraverseFunnel(RichFunnel fn, float deltaTime)
        {
            // Clamp the current position to the navmesh
            // and update the list of upcoming corners in the path
            // and store that in the 'nextCorners' variable
            float   elevation;
            Vector2 position = movementPlane.ToPlane(UpdateTarget(fn), out elevation);

            // Only find nearby walls every 5th frame to improve performance
            if (Time.frameCount % 5 == 0 && wallForce > 0 && wallDist > 0)
            {
                wallBuffer.Clear();
                fn.FindWalls(wallBuffer, wallDist);
            }

            // Target point
            Vector2 targetPoint = waypoint = movementPlane.ToPlane(nextCorners[0]);
            // Direction to target
            Vector2 dir = targetPoint - position;

            // Is the endpoint of the path (part) the current target point
            bool targetIsEndPoint = lastCorner && nextCorners.Count == 1;

            // Normalized direction to the target
            Vector2 normdir = VectorMath.Normalize(dir, out distanceToWaypoint);
            // Calculate force from walls
            Vector2 wallForceVector = CalculateWallForce(position, elevation, normdir);
            Vector2 targetVelocity;

            if (targetIsEndPoint)
            {
                targetVelocity = slowdownTime > 0 ? Vector2.zero : normdir * maxSpeed;

                // Reduce the wall avoidance force as we get closer to our target
                wallForceVector *= System.Math.Min(distanceToWaypoint / 0.5f, 1);

                if (distanceToWaypoint <= endReachedDistance)
                {
                    // END REACHED
                    NextPart();
                }
            }
            else
            {
                var nextNextCorner = nextCorners.Count > 1 ? movementPlane.ToPlane(nextCorners[1]) : position + 2 * dir;
                targetVelocity = (nextNextCorner - targetPoint).normalized * maxSpeed;
            }

            Vector2 accel = MovementUtilities.CalculateAccelerationToReachPoint(targetPoint - position, targetVelocity, velocity2D, acceleration, maxSpeed);

            // Update the velocity using the acceleration
            velocity2D += (accel + wallForceVector * wallForce) * deltaTime;

            // Distance to the end of the path (as the crow flies)
            var distToEndOfPath = fn.DistanceToEndOfPath;
            var slowdownFactor  = slowdownTime > 0 ? distToEndOfPath / (maxSpeed * slowdownTime) : 1;

            velocity2D = MovementUtilities.ClampVelocity(velocity2D, maxSpeed, slowdownFactor, 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 = movementPlane.ToWorld(position + Vector2.ClampMagnitude(velocity2D, distToEndOfPath), elevation);
                rvoController.SetTarget(rvoTarget, velocity2D.magnitude, maxSpeed);
            }

            // Direction and distance to move during this frame
            var deltaPosition = CalculateDeltaToMoveThisFrame(position, distToEndOfPath, deltaTime);

            // Rotate towards the direction we are moving in
            // Slow down the rotation of the character very close to the endpoint of the path to prevent oscillations
            var rotationSpeedFactor = targetIsEndPoint ? Mathf.Clamp01(1.1f * slowdownFactor - 0.1f) : 1f;

            RotateTowards(deltaPosition, rotationSpeed * rotationSpeedFactor * deltaTime);

            Move(movementPlane.ToWorld(position, elevation), movementPlane.ToWorld(deltaPosition, verticalVelocity * deltaTime));
        }