/// <summary> /// This is a coroutine for walking a spline section at constant speed in a defined time duration. /// </summary> /// <remarks> /// Based on the specified duration and the length of the specified spline section it calculates the required speed and then calls WalkAtSpeed. /// </remarks> /// <param name="startIndex">The start index of the spline section. Use start index greater than end index to invert the direction of motion.</param> /// <param name="endIndex">The end index of the spline section. Use end index lesser than start index to invert the direction of motion.</param> /// <param name="duration">The desired duration to cover the spline section.</param> /// <param name="transform">An optional transform object where to apply motion.</param> /// <param name="mode">The SplineWalkerMode: once, loop or ping pong.</param> /// <param name="lookForward">If set to <c>true</c> the transform rotation is set to curve direction.</param> /// <param name="completeFunction">This function will be called upon motion completion (only form SplineWalkerMode.Once).</param> /// <param name="updateFunction">This function will be called every frame.</param> /// <seealso cref="WalkAtSpeed"/> public IEnumerator WalkDuration( int startIndex, int endIndex, float duration, Transform transform, SplineWalkerMode mode = SplineWalkerMode.Once, Boolean lookForward = true, WalkCompleteFunction completeFunction = null, WalkUpdateFunction updateFunction = null) { _UpdateLengths(); // Calculate length from startPoint to endPoint int a = startIndex, b = endIndex; if (a > b) { int tmp = a; a = b; b = tmp; } float l = _arcLengths[b] - _arcLengths[a]; return(WalkAtSpeed(startIndex, endIndex, l / duration, transform, mode, lookForward, completeFunction, updateFunction)); }
/// <summary> /// This is a coroutine for walking a spline section at constant speed. /// </summary> /// <remarks> /// It uses the function GetProgressAtSpeed in order to update the curve parameter at each frame mantaining a constant speed. /// </remarks> /// <param name="startIndex">The start index of the spline section. Use start index greater than end index to invert the direction of motion.</param> /// <param name="endIndex">The end index of the spline section. Use end index lesser than start index to invert the direction of motion.</param> /// <param name="velocity">The desired velocity.</param> /// <param name="transform">An optional transform object where to apply motion.</param> /// <param name="mode">The SplineWalkerMode: once, loop or ping pong.</param> /// <param name="lookForward">If set to <c>true</c> the transform rotation is set to curve direction.</param> /// <param name="completeFunction">This function will be called upon motion completion (only form SplineWalkerMode.Once).</param> /// <param name="updateFunction">This function will be called every frame.</param> /// <seealso cref="WalkDuration"/> public IEnumerator WalkAtSpeed( int startIndex, int endIndex, float velocity, Transform transform = null, SplineWalkerMode mode = SplineWalkerMode.Once, Boolean lookForward = true, WalkCompleteFunction completeFunction = null, WalkUpdateFunction updateFunction = null) { float progress = startIndex / (float)curveCount; float limit = endIndex / (float)curveCount; yield return(GetPoint(progress)); int direction = endIndex > startIndex ? 1 : -1; while (true) { progress = GetProgressAtSpeed(progress, velocity, direction); if ((direction == 1 && progress >= limit) || (direction == -1 && progress <= limit)) { if (mode == SplineWalkerMode.Once) { break; } else if (mode == SplineWalkerMode.PingPong) { direction *= -1; if (direction * (endIndex - startIndex) > 0) { limit = endIndex / (float)curveCount; } else { limit = startIndex / (float)curveCount; } continue; } else if (mode == SplineWalkerMode.Loop) { progress -= limit - startIndex / (float)curveCount; continue; } } Vector3 position = GetPoint(progress); if (transform != null) { transform.position = position; if (lookForward) { transform.LookAt(transform.position + GetDirection(progress)); } } if (updateFunction != null) { updateFunction(position, progress); } yield return(null); } if (completeFunction != null) { completeFunction(); } }