Skip to content

[Niagara] set_module_input_value: LinearColor RGB channels not baked into compiled constants after async compile #122

Description

@lanlin16828-star

Description

When using set_module_input_value to set a LinearColor input (e.g. InitializeParticle.Color), only the Alpha channel is correctly baked into the compiled constants table. The RGB channels fall back to their default values (1, 1, 1).

This makes it impossible to change Niagara particle colors via MCP — the UI shows the correct override value (green), but the preview simulation still renders the old color (white).

Root Cause

File: Source/MonolithNiagara/Private/MonolithNiagaraActions.cpp
Function: HandleSetModuleInputValue (~line 5004)

TargetPin->DefaultValue = ValStr;
GEditor->EndTransaction();
System->RequestCompile(false);   // ⚠ async compile



RequestCompile(false) is asynchronous. When the Niagara compiler bakes the module override values into the VM constant table, the LinearColor pin value has not fully propagated yet. The compiler reads stale/default RGB values.

Simple types (Float, Bool, Int) are not affected because their pin values settle synchronously.

Reproduction
Open any Niagara system with an InitializeParticle module using Color Mode: Direct Set
Via MCP: set_module_input_value → set Color to (R=0, G=1, B=0, A=0.7)
Save + compile
get_module_input_value returns green ✅
get_all_parameters shows {r:1, g:1, b:1} ❌ — only Alpha = 0.7 was applied
Niargara preview renders white particles, but the module UI color swatch shows green
Workaround (confirmed working)
Bind the module input to a User Parameter instead of setting a direct value:

cpp
// 1. Create user parameter with JSON-format value
add_user_parameter("TestSkinColor", type=LinearColor, default={"r":0,"g":1,"b":0,"a":0.7})

// 2. Link module input to user parameter
set_module_input_binding("Color", → "User.TestSkinColor")

// ✅ Compile → preview shows green correctly
This works because user parameter defaults are read at runtime from the ParameterStore, bypassing the compile-time bake entirely.

Suggested Fix
Change RequestCompile(false) to RequestCompile(true) (synchronous), or add a WaitForCompilationComplete() call before the compile starts:

cpp
TargetPin->DefaultValue = ValStr;
GEditor->EndTransaction();
System->WaitForCompilationComplete(false);  // flush pending
System->RequestCompile(false);
Environment
Monolith: v0.22.0
UE: 5.7
Niagara: CPU emitter with InitializeParticle v2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions