Engine versions
What changes between Unreal Engine 5.3 and 5.8 when you call MifBridge: names that are renamed, fields that mean something else, engine bugs that exist on one version only, and answers that report which model they used. Each entry says what you see, why, and what to do.
MifBridge supports UE 5.3 through 5.8. If you are editing the plugin's own C++, read agent-engine-versions instead. The engine list is on /engines.
The rule: never assume a value moves between engines
A call that works on one engine can differ on another in four ways. Check each when a result looks wrong on only one version:
- A name was changed. A display label, a node title or an enum label differs.
- A field was split or repurposed. The same property name now means something else.
- A concept changed model. The same operation uses a different kind of object.
- An engine bug exists on one version only.
Do not test on a single engine and assume the rest match. When the bridge knows two engines disagree, it reports which model answered, so a caller does not learn the difference from a refusal.
Display names are not identifiers
What you see: a value the Details panel shows is refused on one engine and accepted on another, or a node you found by its title on 5.7 is not found on 5.8.
Why: a display name exists to be readable. Epic changes it freely between versions, and carries no compatibility promise. Measured:
| Version | Texture compression TC_EditorIcon is shown as |
The load-primary-asset async node's title |
|---|---|---|
| 5.3 and 5.4 | UserInterface2D (RGBA) |
Async Load Primary Asset |
| 5.5 and 5.6 | UserInterface2D (RGBA8) |
Async Load Primary Asset |
| 5.7 | Uncompressed (RGBA8) |
Async Load Primary Asset |
| 5.8 | not measured | AsyncLoadPrimaryAsset |
Do instead: use the authored name (TC_EditorIcon, AsyncLoadPrimaryAsset), which is the stable identifier. MifBridge reads enums by reflection and carries a short list of aliases keyed to authored names for the ones its help recommends. When you compare a title yourself, strip the spaces and any trailing parenthetical, and compare what distinguishes the outcomes, not the exact spelling. The node had resolved perfectly with the same seven pins on every engine; only its title text changed.
One field, two meanings: the IK Rig retarget root
What you see: on UE 5.8, set_property on an IK Rig's retarget root answers ok:true, changed:true, verified:true, and the rig does not retarget.
Why: UE 5.8 split the one field into two: the root bone (the bone that holds root motion, at the origin) and the pelvis bone (the bone at the hips). What 5.3 through 5.7 called the retarget root is now the pelvis bone on 5.8, and the root-bone field means something new. The old field is still a real, writable property, so every word of the answer is true. The write happened and reads back. Nothing in the retargeting path looks at it.
You can see two readers disagreeing: get_property on the root bone field says pelvis, while list_ik_rig says retargetRoot is None.
Do instead: use set_ik_rig_retarget_root. It goes through the engine's controller, so it follows the split on every engine. When an endpoint exists for a structure, prefer it to set_property on the structure's members: the endpoint tracks what the engine reads, and reflection only tracks what the struct declares.
A concept that changed model: IK solvers
In UE 5.6 the IK Rig solver system moved from objects to structs.
- A solver type is a class on 5.3 and a script struct on 5.6 and later.
solverClassstays a string on both and is valid input toadd_ik_solveron the same engine, but the values are not portable between engines. list_ik_solver_typesreturns asolverModelfield saying which form this engine uses.- The retarget processor is an object on 5.3 and a struct on 5.6 and later. The struct has no accessor for the target rig's inner processor, so one of the three validity checks cannot be made there.
list_retarget_chain_mappingreports aruntimeProbeModelfield naming which checks actually ran, on both engines, so a weaker verdict does not look equally strong.
Do instead: read solverModel and runtimeProbeModel before you carry an id between engines or treat a pass as complete.
5.3 hides the Replicates row for function graphs
The Details panel on 5.3 has no Replicates row for a function graph at all. set_function_flags on a function graph sets real flags the compiler honors, and you cannot verify them by clicking. Verify through the flags the endpoint reports instead. See mistakes-blueprints.
Derived answers
Where an engine call exists on one version only, an endpoint may work out the answer from calls that exist on all of them, and say so in its response. The Game Features endpoints derive a plugin's state from four predicates (installed, registered, loaded, active) because the single call that returns the exact state exists on 5.7 only. Read the answer's own note about whether it is derived before you compare it with the editor.
Deprecated does not mean the old answer still holds
The engine sometimes keeps a deprecated function under its old name and changes what it does. Two shapes are quiet:
- Deprecated and empty. From UE 5.4, the older World Partition actor-descriptor loop (
ForEachActorDesc) is still there and iterates nothing. Code written for 5.3 compiles, runs, and returns a confident empty answer. - Deprecated and constant. On 5.7, several landscape edit-layer checks (
HasLayersContent,CanHaveLayersContent) are deprecated and always return true. A guard that reads one refuses every landscape and looks like it is working.
What to do: if an engine-reading call answers empty or "always yes" on only one version, suspect a deprecated function with a changed body before you suspect the content. MifBridge computes its own answer for these, for example from the edit-layer stack, which is real on every engine.
An engine bug fixed in a later version
Collision on a physics asset: on 5.3, the engine's element lookup has missing break statements. When a per-type index is out of range, it falls through to the next array and returns a different shape type. Asking for sphere 3 on a body with one sphere and five boxes modifies a box. On 5.7 the breaks are there, the lookup returns null, and the engine then dereferences it and stops the editor. The same wrong input edits the wrong primitive silently on 5.3 and ends the editor on 5.7. set_physics_primitive_collision resolves the right array itself and range-checks against that one, so it behaves the same on both.
The older engine is the dangerous half, because the newer one at least fails loudly.
Engine behaviors you will hit on a specific version
These come from the engine, not the bridge, and each is limited to the versions named.
| Version | What you see | What to do |
|---|---|---|
| 5.3 to 5.6 | delete_asset on a map you loaded back answers numDeleted 0 with blockedBy.engineReferencers naming GCObjectReferencer, and the file stays open. 5.7 and 5.8 delete it. |
Remove a throwaway map after leaving it, clearing undo and collecting garbage, before anything loads it again |
| 5.5 and 5.6 | A new ML Deformer model's first save fails with Name "VertexMap" is not mapped when saving. The failed pass leaves the property filled. |
Save again. The second save succeeds |
| 5.6 and 5.7 | Cancelling a clip's compression (reached by SetSkeleton, for one) can deadlock the editor with no CPU use and no log line |
See mistakes-editor-hangs |
| 5.6 | A build without debug symbols can stall about a minute (64 to 67 seconds measured) on a handled ensure, once per call site | A call that times out once and passes on the retry may have met one. Look for "Handled ensure" in the log |
Per-user scalability settings leak into every project
What you see: an effect or grass density measures as zero on one engine version and normal on the others, and nothing in the project explains it.
Why: an engine's scalability groups come from a per-user file, %LOCALAPPDATA%/UnrealEngine/<version>/Saved/Config/WindowsEditor/EditorSettings.ini, section [ScalabilityGroups], on every launch and for every project. If the 5.6 file holds every group at Low, every 5.6 editor starts Low. Then sg.EffectsQuality 0 leaves a Fountain's emitter out, and grass.densityScale 0 grows no grass. Nothing in a project's config is involved, and the log shows only Applying CVar settings from Section [EffectsQuality@0].
Do instead: when you measure an effect or grass, set the quality yourself with set_cvar and its scalability option, and read that section of the file when one engine behaves differently from the others.
Where to go next
- agent-engine-versions for the plugin's C++
- mistakes-calling for strict values and enum names
- mistakes-animation for animation tools