The following is pseudo code, intended as a suggestion. It is not tested, not compiled, and is only intended to illustrate a plan for the answer to your question with our commentary exchanges in mind. It is not a complete class. Interpret for your circumstance and naming conventions.
public class EnemyMovement : MonoBehaviour
Path path; // the path container returned by PathFinder.GetPath()
bool isFollowingPath = false; // bool indicating path is still in progress
int curPathPoint = 0; // the current position in the waypoint list ( path )
Waypoint curWp; // the current Waypoint in path
Waypoint nextWp; // the next Waypoint in path (after current)
float pathTween = 0; // the 'tween' value for lerp
float pathSpeed = 0.1f; // the 'speed' of the tween, or motion between waypoints
PathFinder p = FindObjectOfType<PathFinder>();
// note, path is now a member
path = p.GetPath();
// if there's a path, initialize path finding values
if ( path )
curPathPoint = 0;
SetPathPosition( 0 );
isFollowingPath = true;
void SetPathPosition( int n )
curWp = path[ curPathPoint ];
nextWp = path[ curPathPoint + 1 ];
// increment to the next waypoint, return false
// if the end has been reached
if ( curPathPoint > ( waypoint.Count - 2 ) )
SetPathPosition( curPathPoint );
// no longer a coroutine, step through the
// 'tween' animation between Waypoints
if ( isFollowingPath ) StepFollowPath();
// pathTween moves from 0.0f to 1.0f, such that when
// 1.0f is reached, the current waypoint should be
// increment the pathTween according to pathSpeed
// for current time slice
pathTween += ( pathSpeed * Time.deltaTime );
if ( pathTween >= 1.0f )
// if tween >= 1.0f, the waypoint has been passed,
// move to the next waypoint pair
if ( IncPathPosition() == false )
// when increment returns false, the endpoint was reached
// stop following path
isFollowingPath = false;
// at this point, the pathTween is > 1.0f, and the remainder
// is retained, because it is that portion of the next
// waypoint pair time has already passed by
pathTween -= 1.0f;
// pathTween has been updated, even if that means moving to the
// next waypoint pair
// calculate lerp between current waypoint and next waypoint
// according to the pathTween ratio
transform.position = Vector3.lerp( curWp.transform.position,
The idea begins by eliminating the coroutine. It is getting in the way. Instead, the “loop” is emulated by curPathPoint; it sequences through the path list (I assume that’s a List). Start, here, is your example start but where path is now a member of the class.
Focus first on Update(). Note that is checks if the path is being followed, and calls for a step to be followed through the path. When the path end is reached, isFollowingPath will be set false, so update will stop calling for path animation.
Next, focus on StepFollowPath. It increments one step through the path, with the key feature being that the steps you must animate are not from one waypoint to the next, but lerps between the current waypoint and the next waypoint. This is how jerkiness is eliminated, by animating the transition between two points. pathTween is the ratio between the current and next waypoint, calculated according to pathSpeed for each slice of time through the animation.
When pathTween reaches (or exceeds) 1.0f, the lerp has reached the next waypoint, so then and only then is it appropriate to ‘loop’ to the next waypoint (IncPathPosition). Until pathTween reaches 1.0f , it is somewhere, according to time slice and speed, between 0.0f and 1.0f, indicating that another tiny step between the current waypoint and the next must be incrementally advanced (that’s the purpose of lerp in the first place).
Note that the lerp is calculated as a ‘tween’ between the current waypoint and the next waypoint. That is the animation of small slices of time through the list of waypoints, smoothly.
This represents a plan to implement what I think you’ve described. Let me know if I misunderstood. I doubt this code is ready to paste and use, but read it and interpret it to merge into your next code experiment.