InputModifierNegate / SwizzleAxis / InputTriggerPulse are EditInline-instanced UObjects. Two distinct behaviours, both verified across a save → reload_packages → re-load round-trip:
Direct arrays on the InputAction persist correctly.
new_object(unreal.InputTriggerPulse, outer=IA) → set properties → IA.set_editor_property('triggers', [pulse]) → save. Survives the reload.
Modifiers nested in the IMC mapping-struct array do NOT persist by any scripted path.
Assigning into the struct wrapper reads back fine in memory, but the required write-back
dkm.set_editor_property('mappings', maps)
nulls every instanced modifier — with outer=IA, outer=IMC, a transient outer, via new_object or a default constructor, all the same. The mapping slots keep the correct count; the objects are gone on reload.
Why it is worth an action
The failure mode is a green in-editor session that saves a package whose triggers/modifiers are all None. It was found by debugging a second-player binding that moved in one direction only — nothing in the editor or the logs indicated the write had been dropped.
Since the Python path cannot express this correctly, a native action that constructs and outers the subobject properly would be the only way to author IMC per-key modifiers from script. Today the honest guidance is "author these by hand in the editor", which is the only item in our notes where that is the answer.
Related
#130 adds read-only Enhanced Input asset inspection — this is the write side of the same area, and the two would compose well.
Verification note
Always check input-subobject persistence across a reload rather than an in-memory read: save_asset → reload_packages([pkg]) → re-load_asset → assert triggers[0] / modifiers[0] is not None. An in-memory read passes on transient objects that will be null on disk, which is what made this take a while to pin down.
InputModifierNegate/SwizzleAxis/InputTriggerPulseare EditInline-instanced UObjects. Two distinct behaviours, both verified across asave→reload_packages→ re-load round-trip:Direct arrays on the InputAction persist correctly.
new_object(unreal.InputTriggerPulse, outer=IA)→ set properties →IA.set_editor_property('triggers', [pulse])→ save. Survives the reload.Modifiers nested in the IMC mapping-struct array do NOT persist by any scripted path.
Assigning into the struct wrapper reads back fine in memory, but the required write-back
nulls every instanced modifier — with
outer=IA,outer=IMC, a transient outer, vianew_objector a default constructor, all the same. The mapping slots keep the correct count; the objects are gone on reload.Why it is worth an action
The failure mode is a green in-editor session that saves a package whose triggers/modifiers are all
None. It was found by debugging a second-player binding that moved in one direction only — nothing in the editor or the logs indicated the write had been dropped.Since the Python path cannot express this correctly, a native action that constructs and outers the subobject properly would be the only way to author IMC per-key modifiers from script. Today the honest guidance is "author these by hand in the editor", which is the only item in our notes where that is the answer.
Related
#130 adds read-only Enhanced Input asset inspection — this is the write side of the same area, and the two would compose well.
Verification note
Always check input-subobject persistence across a reload rather than an in-memory read:
save_asset→reload_packages([pkg])→ re-load_asset→ asserttriggers[0]/modifiers[0]is notNone. An in-memory read passes on transient objects that will be null on disk, which is what made this take a while to pin down.