"Kinematic movement that doesn't get stuck"
▸ SYMPTOM
- Player overlaps a collider (slide clip, building placed on top) and never moves again.
- Every trace reports a hit; wish direction zeroes forever.
- After noclip / teleport, exiting inside geometry traps the mover.
▸ CAUSE
Trace-based kinematic controllers have no body collider of their own: collision is entirely in the traces. If the current position is already inside solid, the next trace starts solid and a naive "hit → stop" loop permanent-entraps the player.
▸ FIX
Slide-trace pattern
var wish = Rotation.FromYaw(cameraYaw) * new Vector3(Input.AnalogMove.x, Input.AnalogMove.y, 0);
// … scale wish by speed * dt …
var tr = Scene.Trace.FromTo(pos, pos + wish)
.Radius(radius)
.IgnoreGameObjectHierarchy(go)
.WithoutTags("player", "ghost")
.Run();
if (tr.StartedSolid)
{
// overlapped - ignore collision this frame so they can walk free
pos += wish;
}
else if (tr.Hit)
{
var slide = wish - tr.Normal * wish.Dot(tr.Normal);
var tr2 = Scene.Trace.FromTo(pos, pos + slide)
.Radius(radius)
.IgnoreGameObjectHierarchy(go)
.WithoutTags("player", "ghost")
.Run();
if (!tr2.StartedSolid && !tr2.Hit)
pos += slide;
// else stop / try secondary axis - your call
}
else
{
pos += wish;
}Trace API that works: .Hit, .Normal, .StartedSolid (also .Body, .HitPosition, .Shape, .Collider when you need prop pushes).
Placement / teleport hygiene
- Forbid build placement within the structure's footprint of the player.
- Never teleport "over" geometry by a fixed offset onto per-poly concave meshes: backfaces don't collide; you fall inside the shell with no StartedSolid. Down-trace from the apex, require walkable
normal.z(e.g. ≥ 0.6), land on the hit. - Leaving noclip inside geometry: step the body up until a down-cast no longer starts solid (capped), then return to normal air/ground state.
Jump as pure visual/vertical state if you keep horizontal traces at fixed torso height: track _height / _verticalSpeed yourself.
▸ WHY IT WORKS
StartedSolid means the trace origin is already penetrating. Treating that as a normal wall hit zeroes motion forever. Ignoring collision for that frame (or ejecting) restores a free configuration so later traces can slide correctly again.