Control Rig vs Modular Rig in Unreal Engine 5: which one to use
On 5.6 and 5.7 the modular rig library has no physics modules at all, which decides most of this argument on its own. Plus the outdated module folder, the socket that reads backwards, and an engine bug that silently destroys your tuning.
Loading…
Stop bouncing between AI and Unreal.
Drop the plugin into your project, point your MCP client at it, and let your AI actually build inside the editor.
Short answer: if you are on Unreal Engine 5.6 or 5.7 and the character needs jiggle, cloth sway or any secondary motion, you need a graph rig, because the modular rig library on those versions contains no physics modules at all. That single fact decides most of these arguments before any of the other differences matter.
If you do not need physics, modular is usually the better choice: assemble from prebuilt components, get a working rig faster, keep it consistent across a cast. Below is what each actually is, the version table that decides it, and four traps that cost me real time, one of which is an engine bug that silently destroys your work.
What the two actually are
A graph rig is the original Control Rig: you open a RigVM graph and wire the solve yourself. Forward solve, backward solve, two bone IK nodes, aim constraints, your own maths. Total control, and total responsibility.
A modular rig is assembly. You add prebuilt modules. Root, Spine, Shoulder, Arm, Leg, and connect them through named connectors. Each module ships its own controls, its own solve, and a config surface for tuning. You are composing, not authoring.
The trade is the usual one. Modular gets you a competent biped fast and keeps forty characters consistent. A graph rig does whatever you want, including the things no module author anticipated.
The decider: physics availability by version
This is the part that is hard to find written down, so here it is, read from the shipped plugin descriptors rather than from anyone's blog:
Engine
Plugin
Epic's flag
On by default
5.6
PhysicsControl
Experimental
No
5.7
ControlRigPhysics
Experimental
No
5.8
ControlRigPhysics
Beta
Yes
No version has left Engine/Plugins/Experimental/. Treat rig physics as a beta feature on every engine version, budget iteration time, and do not trust a green status. I have had a rig report perfectly healthy while every control moved nothing.
Verify this on your own install
Do not take the table on faith. Grep the descriptors:grep -E '"(IsBetaVersion|IsExperimentalVersion|EnabledByDefault)"' \
<EngineRoot>/Engine/Plugins/Experimental/{PhysicsControl,ControlRigPhysics}/*.uplugin
And the practical consequence, verified by listing the module library on 5.6: there is no ChainPhysics, no PhysicsSolver, no BipedPhysics, no LimbPhysics. A modular rig on 5.6 or 5.7 cannot have jiggle, because the modules that would provide it do not exist. Graph rigs can, via the physics nodes.
Trap 1: you are probably using the outdated module library
The module library is versioned by generation, and the obvious folder is the wrong one. On 5.6 the current modules live in /ControlRigModules/Modules56/, and on 5.8 in Modules58. The plain /ControlRigModules/Modules/ folder is the previous generation.
List what is actually current:
bash
cfa list_rig_module_assets
On a 5.6 install that returns 21 modules tagged Stable from Modules56, and separately reports 21 excluded as outdated. Same count, different folder, which is exactly how you end up building an entire rig out of the old generation without noticing. Root is the odd one out, living at /ControlRig/Modules/Modules56/Root.Root.
Trap 2: the Arm binds to a socket the Shoulder created
Modules connect through sockets, and sockets are spawned by other modules in a cascade. Root spawns the pelvis socket. Spine spawns the shoulder, neck and thigh sockets. Then the Shoulder module spawns hand_l_socket and hand_r_socket.
So the Arm's primary connector binds to the hand socket, not to anything shoulder-shaped. It reads backwards the first time. Bind it per side and audit both, because binding an arm to the wrong side's socket produces a rig whose right arm generates controls named hand_l_*, which is confusing enough to lose an afternoon to.
On some skeletons the Leg spawns no ball socket
If Foot has nothing to bind to, create the ball sockets by hand and bind the Foot primary to those. Nothing is broken; the module simply does not spawn them for every skeleton.
Trap 3: an engine bug that destroys your tuning on 5.8
This is the one worth knowing before you tune a modular rig on 5.8, because the failure mode is silent and the next save makes it permanent.
A modular rig's config overrides, every value you tuned per module, serialize bound to the module's transient variables property bag. On a cold editor boot, with tab restore being the classic trigger, those bags do not exist yet. Resolving the path fails, and the engine responds by resetting the override. Every module silently reverts to factory defaults, and if you then save, the tuning is gone from disk for good.
The tell is in the log:
Error when loading override for path 'X': 'Path is not valid.'
If you see that, do not save
The asset on disk still holds your overrides at that point, only the in-memory copy was reset. Restart the editor and let the bags initialise. Saving is what makes the loss permanent.
It masquerades as random "my settings keep getting lost", because a long-lived editor never hits it, the bags already exist, so everything works fine all day. It only bites on a cold boot, which is exactly when you are least likely to connect cause and effect.
Trap 4: config writes that appear to do nothing
Writing a module config updates the blueprint model and the class default object. The instance you are actually looking at only picks that up during initialisation. If the editor is unfocused or running unattended it may never tick that path, so your change is real, saved, and invisible, and every readback reports the old value.
I lost hours to "changing the collision size does nothing" before finding this. The fix is to force the rig to re-initialise after a config write rather than assuming the write took.
Read the modules back to confirm state:
bash
cfa list_rig_modules --asset-path "/Game/Rigs/MR_Character"
A measurement trap on 5.6
list_rig_modules does not populate the connector target field on 5.6, every target reads None even for connectors that demonstrably resolved. A fully bound rig looks completely unbound. Do not debug the binding; debug your measurement.
So which one
Pick modular when you have a cast of humanoids that need competent, consistent rigs, you are on 5.8 or you do not need physics, and you would rather tune parameters than author solves.
Pick a graph rig when you need physics on 5.6 or 5.7, when the character is not a standard biped, or when the rig has to do something specific enough that no module covers it, bespoke IK behaviour, custom ground adaptation, anything you would otherwise fight a module to achieve.
For a hero character you are art-directing, you will end up in a graph rig eventually regardless. For the other forty, modular is the answer, and the traps above are most of what stands between you and a working one.
However you build it, prove it evaluates
The single most common way to waste a day on either kind of rig is trusting a status. A call that did not error only tells you it did not error. It says nothing about whether the rig actually moves anything.
Run it and read what moved:
bash
cfa simulate_rig --asset-path "/Game/Rigs/CR_Character" --anim-sequence "/Game/Anims/A_Walk" --frames 90
That reports which bones moved and by how much, whether limbs crossed through each other, whether anything dropped below the floor, and whether any transform came back NaN. A verdict, rather than a status.
Every finding above came out of building these rigs, not reading about them. 900+ commands across 28 categories, on UE 5.6, 5.7 and 5.8. Drive it from Claude Code, Cursor, VS Code, or any MCP client.
Three day free trial. No card, nothing locked off, and it runs on your real project.