Summary
In cooked (non-editor) builds, the Control Rig node Get Short Name (FRigUnit_GetItemShortName) returns the element’s full module-qualified name (Neck/Global) instead of its short name (Global).
The node calls URigHierarchy::GetDisplayNameForUI(Item, EElementNameDisplayMode::ForceShort). The non-WITH_EDITOR branch of that function ignores the display mode and returns the full FName:
// RigHierarchy.cpp, URigHierarchy::GetDisplayNameForUI (UE 5.8)
#else
return FText::FromName(InElement->GetFName());
#endif
The FortniteRigs library function Construct Space Nulls v01 (/FortniteRigs/Libraries/CRFL_Control_v001) uses Get Short Name to build orient-space null names. In packaged builds the names collide and get auto-suffixed, so controls bind to the wrong orient spaces. In the stock Zebra sample, the neck, head and right arm pose is wrong in every packaged build. PIE is correct.
What Type of Bug are you experiencing?
Animation
Steps to Reproduce
- Create a project from the Zebra sample in UE 5.8 (Epic Games Launcher build).
- Open
/Game/Mainand Play In Editor./Game/Sequences/zebra_auditionauto-plays. Watch the head near sequence frames 197, 413, 605 and 653 (24 fps). - Package for Windows (Development) and run the build. Watch the same frames.
- In the packaged build the head and neck are rotated and look badly deformed (head is looking down at the ground instead of teh camera). The right arm is also off.
Minimal repro without the sample (from the code path, not built separately):
- In a modular rig, feed a module element such as
MyModule/Foointo Get Short Name. - Editor/PIE returns
Foo. A cooked build returnsMyModule/Foo.
Expected Result
Get Short Name returns the same short name in editor and cooked builds (Global for Neck/Global). FortniteRigs space nulls get the same names in PIE and packaged builds, and the packaged pose matches PIE.
Observed Result
In cooked builds Get Short Name returns the full name. Construct Space Nulls v01 then builds names like Neck/Start FK Neck/Global Orient Space. The hierarchy keeps only the last path segment, so the names collide:
| Space null for | PIE (correct) | Packaged |
|---|---|---|
| Neck Start IK | Neck/Start IK Global Orient Space |
Neck/Global Orient Space |
| Neck Start FK | Neck/Start FK Global Orient Space |
Neck/Global Orient Space_2 |
| Neck End IK | Neck/End IK Global Orient Space |
Neck/Global Orient Space_3 |
| Neck End FK | Neck/End FK Global Orient Space |
Neck/Global Orient Space_4 |
| Arm R FK 0 | Arm R/FK 0 Body Orient Space |
Arm R/Body Orient Space |
The same pattern appears on Spine, both Arms, both Legs and both Clavicles. Bone-based spaces (... spine_05 Orient Space) are correct in both builds, because bone names have no module prefix.
Measured against PIE at the same sequence frames (component space): neck_02 is off by up to 41°, head by up to 89°, and upperarm_r by up to 37°. Sequencer control values are identical in both builds. Only the controls’ parent orient spaces differ.
Affects Versions
5.8
Platform(s)
Android
Windows
Upload an image
Additional Notes
Suggested engine fix: make the non-editor branch of GetDisplayNameForUI honor ForceShort and Auto by splitting the module path (FRigHierarchyModulePath(...).Split(nullptr, &ShortName)). Alternatively, make FRigUnit_GetItemShortName split the item name directly instead of calling a UI function.
Content workaround (verified): in CRFL_Control_v001 → Construct Space Nulls v01, replace Get Short Name with: Get Item Module → Length(Module) + To Integer(IsPartOfModule) → Chop(Item.Name, Count, From End = false).Remainder. Then recompile and resave the modules that call the function: CRM_FN_Spine, CRM_FN_FkArray, CRM_FN_FkChain and CRM_FN_IkFk2Bones. Chop defaults to From End = true, so set it explicitly.
With this change, PIE is unchanged, and the packaged pose matches PIE exactly: bones, anim curves and all rig elements over 32 sampled frames.
How we verified: a runtime capture paused zebra_audition at fixed frames and dumped component-space bones, curves and the MR_Zebra hierarchy, in PIE and in the packaged build. Two packaged runs matched each other exactly, so the comparison has no noise.
