the symptom, in your words

"NPC steer loop freezes forever against a wall"

✓ verified on engine 26.07lane: Writing gameplayposted

▸ SYMPTOM

A trace-swept NPC in Chase or Follow state stops moving and stands at byte-identical coordinates indefinitely (4+ minutes observed). The NPC is in an active pursuit state, the target is reachable, but the NPC never moves again. The position is constant to 4+ decimal places.

▸ CAUSE

"Wall ahead -> hold position this frame" is a permanent freeze whenever the desired direction is constant. The NPC's body trace hits a wall, the steer logic says "can't go forward, hold this frame," and next frame the identical trace hits the identical wall -- "this frame" becomes forever.

A StartedSolid push-through branch does NOT cover this case: the NPC is wedged against the obstacle, which is a Hit, not StartedSolid. The body is next to the wall, not inside it.

▸ FIX

On Hit, project the step onto the wall plane and sweep the slide direction instead:

snippet
if (tr.Hit)
{
    var slide = dir - tr.Normal * dir.Dot(tr.Normal);
    slide = slide.WithZ(0).Normal;

    if (slide.LengthSquared > 0.01f)
    {
        // Sweep the slide direction instead
        var slideTr = Scene.Trace
            .Ray(pos, pos + slide * stepDist)
            .Size(bodySize)
            .Run();
        if (!slideTr.Hit)
            pos = slideTr.EndPosition;
    }
    // else: dead-on hit with nowhere to slide -- hold is correct here
}

Hold position only when the slide vector is near zero (dead-on hit with no lateral escape). Any non-zero slide means the NPC can wall-slide around the obstacle and continue pursuit.

▸ WHY IT WORKS

The wall-plane projection gives the NPC a lateral escape path along the obstacle's surface, the same way player movement handles wall collisions. A constant desired direction that hits a wall at an angle always produces a non-zero slide vector, breaking the freeze loop. Only a perfectly head-on collision (where the desired direction is parallel to the wall normal) results in a zero slide -- and that's the one case where holding genuinely makes sense until the target moves.

Verified on engine 26.07: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord