Quick answer: The default knot index parameterization makes equal t increments cover unequal arc lengths. At slow speed this is visible as stutter. Track distance in meters and use SplineUtility.GetPointAtLinearDistance for constant world-space speed.

Here is how to fix Unity Splines package walkers that stutter, jitter, or move at uneven speeds along a curve. Your follower advances smoothly along straight sections, then visibly slows or jumps in tighter curves. The issue is the parameterization: t goes 0→1 across the whole spline, but a unit of t in a tight curve covers far less world space than the same t on a straight section.

The Symptom

An object follows a spline using the Splines package. At normal speed (5+ m/s) the motion looks fine. At slow speeds (less than 1 m/s), the object stutters — you can see it pause briefly at curves and then catch up on straights. The framerate is steady; only the per-frame movement varies.

What Causes This

Knot-index parameterization. By default, Unity Splines parameterize by knot index. t = 0.5 sits halfway through the knot count, not halfway along the arc length. With non-uniform knot spacing, equal t deltas produce unequal arc deltas.

Per-frame t increment too small. At low speeds, you advance t by tiny amounts. Floating-point precision loses sub-knot positions, snapping the object to the nearest discrete sample.

Tight curves with low knot density. A 90-degree turn with only two knots on either side has heavy tangent inflation between them. Mid-curve, the spline curves sharply, but the parameterization still ticks linearly.

Update vs FixedUpdate timing. If you update position in FixedUpdate but render interpolation interpolates against an outdated parameter, the visual stutter is a sampling artifact.

The Fix

Step 1: Switch to distance-based traversal.

using UnityEngine;
using UnityEngine.Splines;

[RequireComponent(typeof(SplineContainer))]
public class SplineWalker : MonoBehaviour
{
    [SerializeField] private SplineContainer container;
    [SerializeField] private float speedMetersPerSec = 2f;

    private float distance;
    private float totalLength;

    void Start()
    {
        totalLength = SplineUtility.CalculateLength(container.Spline, container.transform.localToWorldMatrix);
    }

    void Update()
    {
        distance += speedMetersPerSec * Time.deltaTime;
        if (distance >= totalLength) distance -= totalLength;

        SplineUtility.GetPointAtLinearDistance(
            container.Spline, distance / totalLength, distance, out float tAtDistance);

        Vector3 pos = container.EvaluatePosition(tAtDistance);
        Vector3 fwd = (Vector3)container.EvaluateTangent(tAtDistance);
        transform.position = pos;
        if (fwd != Vector3.zero) transform.rotation = Quaternion.LookRotation(fwd);
    }
}

Distance parameterization keeps motion at exactly speedMetersPerSec regardless of knot density.

Step 2: Add knots through tight curves. In the Spline Editor, insert extra knots in sections that curve sharply. More knots means smoother per-distance evaluation.

Step 3: Smooth tangent modes. Select all knots, set their tangent mode to Auto Smooth or Mirrored. This eliminates abrupt direction changes at knot boundaries.

Step 4: Move in FixedUpdate for physics-tied followers. If the walker drives a Rigidbody, do the position update in FixedUpdate using the physics delta. Use Rigidbody.MovePosition rather than direct transform.position assignment so interpolation smooths intermediate frames.

void FixedUpdate()
{
    distance += speedMetersPerSec * Time.fixedDeltaTime;
    if (distance >= totalLength) distance -= totalLength;
    rb.MovePosition(GetPointAlongSpline(distance));
}

Step 5: Cache spline length once. CalculateLength is not free. Compute on Start and recompute only when the spline changes. Subscribe to SplineContainer.Spline.changed if you allow runtime edits.

Verifying Smoothness

Add a simple debug line that records the walker’s position every frame. After a slow lap, the trail should be evenly spaced. If you see clustering at curves, distance parameterization is not yet active or knot density is too low. If you see clustering at straights, your speed code is the issue.

“Splines move you by t. Players see meters. The two are not the same. Walk by distance, not by parameter.”

Related Issues

For Cinemachine following splines, see Cinemachine Camera Jitter. For physics-based motion, see Physics Jittery Movement.

Distance parameterization. Smooth tangents. FixedUpdate for physics. The walker glides.