# Why do I get a jitter/stutter when moving and following a target?

I am using the script below to move a transform to quickly follow a target (the player), and come to a stop close to the player.

When I move the player around, the transform is following the player, keeping the 1.5 distance.

To ensure the transform can keep up with the player, I set the moveSpeed to 5, But when I do that, the transform jitters/stutters when moving.

If I set the moveSpeed to 1 for example, the transform will move smoothly but will not keep up with the player - the player has to stop moving and wait for it to catch up. But increasing the speed makes the stutter return.

Why is this stutter happening, and how can I make the movement smooth?

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

{
public Transform targetToFollow;
public Text text;
public Text text1;
public float lookAtRotationSpeed;
public float moveSpeed;

private float minMoveSpeed = 0f;
private Vector3 originPos;

// Start is called before the first frame update
void Start()
{
originPos = targetToFollow.position;
}

// Update is called once per frame
void Update()
{
Vector3 lTargetDir = targetToFollow.position - transform.position;
lTargetDir.y = 0.0f;
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(lTargetDir), Time.time * lookAtRotationSpeed);

var distance = Vector3.Distance(transform.position, targetToFollow.position);

text.text = "Transform Distance From Target " + distance.ToString();

float ms = moveSpeed;

if (distance > 5f)
{
ms = moveSpeed + 0.5f;
}
else if (distance < 1.5f)
{
ms = Mathf.Max(minMoveSpeed, ms - 0.3f);
}
else
{
//transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * ms);
}

if (distance < 0.5f && originPos == targetToFollow.position)
{
ms = 0f;
}

if (distance > 1.5f)
transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * ms);

originPos = targetToFollow.position;
}
}


You have two hard cutoffs in your code:

if (distance > 5f)
{
ms = moveSpeed + 0.5f;
}


This switches to a higher seed if the object is more than 5 units away.

if (distance > 1.5f)
transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * ms);


This moves the object only if the object is more than 1.5 units away.

Consider what happens when your distance is close to one of these thresholds.

• On frame 1, I'm 1.51 units away.

That's more than 1.5, so I take a step of .16 units, now I'm 1.34 units away

• On frame 2, my target has moved .1 units further away, so now I'm 1.44 units from it.

That's less than 1.5, so I don't move.

• On frame 3, my target has moved .1 units again, so now I'm 1.54 units from it.

That's more than 1.5, so I take a step of .16 units, now I'm 1.38 units away.

• On frame 5, my target has moved .1 units again, so now I'm 1.48 units from it.

That's less than 1.5, so I don't move.

You can see, instead of approaching at a slow rate to keep pace with the object I'm following, I stop and start. On alternating frames I find myself too far (so I move and overshoot) or too close (so I stop), creating a jerky, stuttering movement.

The same thing can happen more subtly at the 5 unit cutoff, where I alternate between taking big steps (because I'm just past 5 units) and small steps (because I'm just under 5 units).

You can solve the hard movement cutoff by aiming for the place where you would want to stop. That way you take a smaller move when you're very close, rather than overshooting.

float followRadius = 1.5f;

// Compute a position no further than followRadius away from our target.
Vector3 stopPoint = targetToFollow.position + fromTarget;

// Move as far as we can at our speed ms to reach the stopPoint, without overshooting.
transform.position = Vector3.MoveTowards(transform.position, stopPoint, Time.deltaTime * ms);


To solve the sharp speed change you get at the 5 unit mark, you can blend the speed gradually over a longer distance, something like...

float fastRadius = 5f;
float speedBoost = 0.5f;


This has you moving at your normal move speed when close to the followRadius, and at your faster speed when at/beyond your fastRadius, with a smooth acceleration/deceleration in between.
• You can increase the moveSpeed or speedBoost variables if the transform is not moving fast enough for your needs. – DMGregory Dec 19 '20 at 21:46