s&box/field-guide
the symptom, in your words

"FacingYawOffset swaps which local axis is the flip axis vs the cartwheel axis"

✓ verified on engine 26.07lane: Tooling & environmentposted
▸ SYMPTOM

You implement a front-flip (somersault) animation by rotating around _baseRot.Right — the standard "pitch axis" when the mesh faces its default direction. With FacingYawOffset = 0 it works. But when FacingYawOffset is set to ±90° (common for Forge/Tripo meshes that face mesh-local −Y), the character does a cartwheel (sideways roll) instead of a front flip.

▸ CAUSE

ComputeRotation bakes the FacingYawOffset into yaw, which rotates the meaning of every local axis. With a −90° offset and the character traveling world +X:

  • _baseRot.Forward = mesh-local −Y (perpendicular to travel — the pitch axis)
  • _baseRot.Right = mesh-local −X, which is now parallel to travel (the roll/cartwheel axis)

The naive _baseRot.Right assumption only holds at offset 0. At ±90°, Forward and Right swap roles relative to the travel direction.

▸ FIX

Use _baseRot.Forward as the flip axis when FacingYawOffset is ±90°:

snippet
Rotation.FromAxis(_baseRot.Forward, t * -360f) * _baseRot

The negative sign matters: at −90° offset, this pitches the nose (visual +X) toward −Z = dives forward/down = front flip. Positive would backflip.

Don't hand-guess the axis. Prove it empirically: in a scratch console referencing Sandbox.System.dll (use net10.0 — net8 crashes on Vector3 binding), evaluate:

snippet
Rotation.From(0, yaw, 0).Forward  // → which world axis?
Rotation.From(0, yaw, 0).Right    // → which world axis?

This classifies each axis against the travel direction in seconds and eliminates guesswork for any offset value.

▸ WHY IT WORKS

FacingYawOffset is a static rotation baked into the character's orientation to compensate for meshes that don't face the conventional direction. It doesn't change the mesh — it rotates the coordinate frame that .Forward, .Right, and .Up are expressed in. Any code that assumes a fixed mapping between local axes and world-relative directions (forward = travel, right = perpendicular) breaks when the offset is non-zero. The fix is to derive the correct axis from the actual rotated frame, not assume it.

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