euler order mismatches between Blender, Unity, and Unreal have cost me more hours than I want to admit

219 views 11 replies

This has been my nemesis for years and I keep seeing people run into it silently. They export from Blender, import into Unity or Unreal, something is slightly wrong with a rotation on one specific bone, and they assume it's a rig issue or an FBX exporter bug. Sometimes it is. But often it's euler order.

Quick version for anyone who hasn't hit this wall yet: Blender defaults to XYZ euler order for rotations. Unity works in quaternions internally but its euler representation applies rotations in a different order. Unreal's Rotator (Pitch/Yaw/Roll) maps axes differently again, and all three apps have different coordinate handedness on top of that. A rotation that looks correct in Blender isn't guaranteed to mean the same thing when reconstructed in Unity or Unreal, even if the numbers look identical.

Most of the time the FBX pipeline silently saves you by baking everything to quaternions on export. But the moment you touch anything non-trivial, like constraint-driven bones, driver-based rotation channels, or anything hitting euler values directly, the mismatch resurfaces. I had a shoulder bone that looked perfectly fine in Blender and showed a 90-degree flip in Unity that took two days to trace back to this exact problem.

The fix was switching that bone's rotation mode in Blender to match the export target's convention. That caused gimbal lock in a completely different pose. So I baked to quaternions instead. Then the FBX exporter didn't handle quaternion animation curves cleanly and... you see where this goes.

I've landed on baking everything to euler with a manual axis correction script before FBX export as my working approach. Feels like it shouldn't be the answer in 2026 but here we are.

Curious what workflows others are using. Is this a Blender-specific pain point or have people hit this coming from Maya or Max too? And does anyone have a clean solution for driver-driven bones specifically, without a manual rebake every single time?

Replying to CipherHaze: the handedness flip on top of all of this is what broke me the first time. blend...

the silent axis mirror is genuinely the worst part of this whole mess. FBX exporters often handle the handedness conversion by negating a scale component — so the mesh looks completely correct in the viewport, but the actual bone transforms in code are mirrored. if you're doing anything procedural on top of the animation data — IK solvers, reading bone world positions for VFX attachment, ragdoll anchor points — you're getting subtly wrong results and you won't notice for a long time.

had this happen on a project where foot IK was placing the left foot very slightly to the right of where it should land on uneven terrain. looked almost right. someone pointed it out three months in.

slow realization facepalm
Replying to IronForge: The coordinate axis mapping on top of the euler order problem is what really get...

knowing all of this and still getting burned every few months is apparently just part of the job. the thing that actually helped me was making a habit of exporting a simple arrow mesh pointing in world +X from whatever DCC i'm in, importing it into the target engine before touching any animation data, and verifying it lands where i expect. 30 seconds, saves multi-hour debugging sessions, should be step one every time.

also blender's fbx exporter has an "apply unit scale" checkbox that interacts with axis conversion in ways that feel completely undocumented. unchecked it once by accident and spent two hours convinced my euler order was wrong when it was actually just a scale mismatch warping the rotation display.

it keeps happening
Replying to EchoCrow: would you mind sharing that script? catching cases where a bone ends up with 180...

Not the original poster but I've got something similar. Fires as an AssetPostprocessor on every FBX import and flags bones with near-180 rest rotations:

using UnityEditor;
using UnityEngine;

public class BoneRotationValidator : AssetPostprocessor
{
    void OnPostprocessModel(GameObject root)
    {
        foreach (var t in root.GetComponentsInChildren<Transform>())
        {
            var euler = t.localEulerAngles;
            bool suspect =
                Mathf.Abs(Mathf.DeltaAngle(euler.x, 180f)) < 2f ||
                Mathf.Abs(Mathf.DeltaAngle(euler.y, 180f)) < 2f ||
                Mathf.Abs(Mathf.DeltaAngle(euler.z, 180f)) < 2f;
            if (suspect)
                Debug.LogWarning($"[BoneCheck] {t.name}: suspicious rest rotation {euler}", root);
        }
    }
}

It won't tell you why a bone is wrong, just surfaces the ones worth double-checking. But it's caught a few bad FBX imports before they made it into the project and caused problems we didn't notice until later.

The frustrating part is that this is solvable at the tooling level. FBX and Alembic both carry axis convention and rotation order metadata. The problem is that every DCC and engine reads those fields inconsistently, or quietly ignores them when it's inconvenient. USD is probably the best shot we have right now; the major tools actually respect its axis and unit metadata consistently at this point. Not expecting a cross-industry fix anytime soon, but at least there's a direction that isn't 'just memorize all the conversion tables.'

Replying to ByteBloom: Something that saved me a lot of pain: before touching any real assets, export a...

I'd also make the test mesh show both forward and up, not just forward. A box with a bright green top face and a red front face tells you both axes at a glance. I've been burned by an arrow that looked correct in the target engine but was actually rolled 180°. I'd fixed the forward axis and introduced an up-flip in the process. The two-color box catches those combinations instantly where a plain arrow won't.

One thing that's helped me catch these early: a small Unity editor script that runs post-import and checks every bone's local rotation at rest pose against a sane range. Nothing should be sitting at 179 degrees on an axis that should be near zero at bind. It doesn't fix anything automatically, it just logs a warning so you know to investigate before the problem hides in production for three weeks.

Worth flagging separately: with Unity's humanoid retargeting enabled, the euler order problem can show up during the retargeting pass rather than at import. The raw data looks fine in the model inspector, but Unity re-interprets rotations internally and you end up with a bone that's off by exactly the amount that only shows up at an extreme pose. Took me a long time to connect those dots the first time around.

Replying to IronForge: The coordinate axis mapping on top of the euler order problem is what really get...

the handedness flip on top of all of this is what broke me the first time. blender is right-handed, unity is left-handed, and even when you nail the euler order you can still get a silent axis mirror. spent an entire afternoon convinced my FBX export settings were broken. turned out it was just a Z-handedness flip the whole time, exporter was doing exactly what it was supposed to.

the fact that axis mapping, handedness, and euler order are three completely separate things that all compound on each other is just cruel. brain explode math equations

Replying to ShadowWolf: One thing that's helped me catch these early: a small Unity editor script that r...

would you mind sharing that script? catching cases where a bone ends up with 180/0/0 vs 0/180/0 at import time sounds really useful. those two are visually identical at rest but the keyframe math downstream is completely different, and that's exactly what bites me on more complex rigs.

What's frustrating about this whole problem is how much of it is knowable at import time and just gets silently papered over. FBX has axis convention metadata in the global settings block. Rotation order is specified per-curve in the animation layer data. Both Blender's exporter and Unity's importer have access to all of this — they're just not fully agreeing on how to interpret it, and neither fails loudly when something goes wrong.

I've started keeping a short handoff doc per project: source DCC and version, target engine, any axis or rotation order overrides applied manually, bone names that needed fixes. It's tedious but it's saved me from rediscovering the same issues months in when a second batch of assets arrives from a different source or after a software update changes exporter defaults.

The real fix would be automated round-trip validation: export a reference armature, import it, compare the transforms programmatically, fail the build if anything drifted. Has anyone actually wired something like this into CI? Feels like it should exist as a standard pipeline step by now.

The coordinate axis mapping on top of the euler order problem is what really gets people and it doesn't get called out enough. Blender is Z-up, Y-forward. Unity is Y-up, Z-forward. Unreal is Z-up, X-forward. So even after you nail the euler order, the axis handedness is still waiting to bite you, especially on anything rotating around the world up axis, which is basically everything.

I started keeping a reference scene with a clearly asymmetric object (one arm raised, something held on one specific side) that I export through every new pipeline just to catch this early. Fifteen minutes of sanity checking before you animate anything beats three hours of "wait why is this shoulder rotating backwards" later.

Something that saved me a lot of pain: before touching any real assets, export a test scene with a single mesh (just an arrow or cone pointing in world +X) and import it into the target engine. If it doesn't point in +X after the round trip, you know exactly what axis or euler conversion you're missing before the problem shows up buried inside a character rig on frame 3 of an attack animation. Five minutes to set up, has saved me hours of confusion multiple times.

Moonjump
Forum Search Shader Sandbox
Sign In Register