Skip to content

fix(niagara): emitter resolution, honor emitterName, real accel/size/color modules, stack-module readback#480

Merged
ChiR24 merged 1 commit into
ChiR24:devfrom
SoloGorilla:fix/niagara-emitter-and-modules
Jul 7, 2026
Merged

fix(niagara): emitter resolution, honor emitterName, real accel/size/color modules, stack-module readback#480
ChiR24 merged 1 commit into
ChiR24:devfrom
SoloGorilla:fix/niagara-emitter-and-modules

Conversation

@SoloGorilla

Copy link
Copy Markdown
Contributor

Problem

manage_effect Niagara module actions were unusable end-to-end:

  • All add_*_module actions failed EMITTER_NOT_FOUND. The dispatch layer defaults emitterName to "DefaultEmitter" when the caller omits it, but AddEmitterToSystem names the emitter handle after the source emitter asset, so the exact-match lookup in LoadSystemAndEmitter never matches.
  • add_emitter_to_system ignored a caller-supplied emitterName entirely.
  • add_acceleration_module / add_size_module / add_color_module added User.MCP_* parameters instead of real Niagara stack modules — particles never rendered, though success:true was returned.
  • get_niagara_info reported emitters + user parameters but no stack modules, so a real module was indistinguishable from a parameter shim.

Fix (Domains/NiagaraAuthoring/)

  1. LoadSystemAndEmitter — single-emitter fallback: if the requested name isn't found and the system has exactly one emitter, resolve to it and surface emitterResolvedBy/requestedEmitterName/resolvedEmitterName. Still errors for 0 or >1 emitters.
  2. AddEmitterToSystem — honor a caller-supplied emitterName via FNiagaraEmitterHandle::SetName (also makes the handle name consistent with what module actions resolve against).
  3. AddAcceleration/Size/Color — replace the User.MCP_* shims with real AddModuleToEmitterStack calls (Update/Forces/AccelerationForce, Update/Size/ScaleSpriteSize, Update/Color/Color), mirroring the existing AddForceModule pattern.
  4. get_niagara_info — enumerate per-emitter stack modules by walking the script graph's UNiagaraNodeFunctionCall nodes filtered on GetCalledUsage()==Module. (FNiagaraStackGraphUtilities::GetOrderedModuleNodes is declared but not NIAGARAEDITOR_API-exported, so it can't be linked from the plugin module.)

Validation (UE 5.8, live)

add_emitter_to_system emitterName=FireEmitter → handle named FireEmitter; add_spawn_rate_module (no emitterName) → moduleAdded:true via single-emitter fallback; accel/size/color → real modules; get_niagara_infomoduleCount:12 incl. AccelerationForce/ScaleSpriteSize/Color, userParameterCount:0.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c14b9352-6386-426c-a3a4-ef3e4ec2e4dd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Four Niagara authoring handler files are updated: emitter resolution gains a single-emitter fallback and richer error messages; AddEmitterToSystem optionally renames the new emitter handle; AddModuleAndVerify tightens failure handling; AddAccelerationModule, AddSizeModule, and AddColorModule are rewritten to use AddModuleAndVerify; and AddSystemInfo gains optional per-emitter module enumeration via graph walking.

Changes

Niagara Authoring Improvements

Layer / File(s) Summary
Emitter handle fallback and optional rename on add
plugins/McpAutomationBridge/.../McpAutomationBridge_NiagaraAuthoringHandlersContext.cpp, plugins/McpAutomationBridge/.../McpAutomationBridge_NiagaraAuthoringHandlersSystems.cpp
LoadSystemAndEmitter auto-selects the sole emitter when an exact name match fails, writing resolution metadata or a detailed error with emitter count. AddEmitterToSystem optionally renames the new handle from Context.EmitterName and derives AddedEmitterName from the handle for result fields.
Particle module handlers refactored to AddModuleAndVerify
plugins/McpAutomationBridge/.../McpAutomationBridge_NiagaraAuthoringHandlersParticleModules.cpp
AddModuleAndVerify now fails early on module insertion failure without proceeding to mark dirty/verify. AddAccelerationModule, AddSizeModule, and AddColorModule are rewritten to add modules via AddModuleAndVerify, parse optional JSON inputs with defaults (e.g., Z = -980 for acceleration, white for color), and populate module-specific result fields; the prior LoadSystemOrError/AddOrSet*UserParameter path and parameterAdded/parameterName outputs are removed.
System info extended with per-emitter module list
plugins/McpAutomationBridge/.../McpAutomationBridge_NiagaraAuthoringHandlersInfoValidation.cpp
AddSystemInfo walks each emitter's script graph for function-call nodes filtered by Module usage (guarded by MCP_HAS_NIAGARA_STACK_GRAPH_UTILITIES) and appends a modules array and moduleCount to each emitter's JSON object.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ChiR24/Unreal_mcp#359: Both PRs update Niagara system/emitter name resolution logic to better honor caller-provided values and handle mismatches during emitter/system creation.

Suggested labels

area/server

Poem

🐇 A bunny checks each emitter by name,
Falls back to one if others came—
Modules added, renamed with care,
Graph-walked JSON fills the air,
Acceleration, size, and hue delight,
Niagara particles burst with light! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the four main fixes: emitter resolution fallback, honoring emitterName parameter, implementing real acceleration/size/color modules, and adding stack-module readback to info retrieval.
Description check ✅ Passed The description comprehensively addresses all template sections with clear problem statement, detailed fix explanation, and validation results, covering the four key changes across the Niagara authoring module.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the bug Something isn't working label Jun 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/McpAutomationBridge_NiagaraAuthoringHandlersParticleModules.cpp`:
- Around line 76-93: The parsed Acceleration values are never actually applied
to the Niagara module that was created. After the AddModuleAndVerify call
succeeds and the System reference is populated, you must author the parsed
Acceleration vector values (Acceleration.X, Acceleration.Y, Acceleration.Z) to
the actual module node in the Niagara stack. Currently, the code only copies
these values into Context.Result for the response, but the module itself remains
unconfigured. Add the necessary calls to apply these input parameters to the
created module node after the AddModuleAndVerify call and before setting
Context.Result values.
- Around line 82-93: The AddModuleAndVerify function call is not properly
checking whether the module was actually added before proceeding to set result
fields and call SendSuccess. When AddModuleAndVerify returns false (indicating
the module was not successfully added), the handler should treat this as an
error and return early or call an error response instead of continuing to set
the result fields and calling SendSuccess. Add a proper check after the
AddModuleAndVerify call to verify the module was actually added, and if it was
not, handle it as an error case by returning false or calling an appropriate
error response method before reaching the SendSuccess call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5bc8f4d2-3f01-499f-8d1e-e4f0b394b6da

📥 Commits

Reviewing files that changed from the base of the PR and between e1ceb64 and 7178c3a.

📒 Files selected for processing (4)
  • plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/McpAutomationBridge_NiagaraAuthoringHandlersContext.cpp
  • plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/McpAutomationBridge_NiagaraAuthoringHandlersInfoValidation.cpp
  • plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/McpAutomationBridge_NiagaraAuthoringHandlersParticleModules.cpp
  • plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/McpAutomationBridge_NiagaraAuthoringHandlersSystems.cpp

Comment on lines 76 to 93
const TSharedPtr<FJsonObject>* AccelObj;
FVector Acceleration = FVector(0, 0, -980);
if (Context.Payload->TryGetObjectField(TEXT("acceleration"), AccelObj))
{
Acceleration = GetVectorFromJson(*AccelObj);
}
UNiagaraSystem* System = LoadSystemOrError(Context);
if (!System)
UNiagaraSystem* System = nullptr;
if (!AddModuleAndVerify(Context, TEXT("/Niagara/Modules/Update/Forces/AccelerationForce.AccelerationForce"), ENiagaraScriptUsage::ParticleUpdateScript, TEXT("Acceleration Force"), System))
{
return true;
}
const bool bParameterAdded = AddOrSetVectorUserParameter(System, TEXT("MCP_Acceleration"), Acceleration);
MarkDirtyAndVerify(Context, System);
Context.Result->SetStringField(TEXT("moduleName"), TEXT("Acceleration"));
Context.Result->SetBoolField(TEXT("parameterAdded"), bParameterAdded);
Context.Result->SetStringField(TEXT("parameterName"), TEXT("MCP_Acceleration"));
Context.Result->SetStringField(TEXT("message"), TEXT("Configured acceleration module."));
Context.SendSuccess(true, TEXT("Acceleration module configured."));
Context.Result->SetNumberField(TEXT("accelerationX"), Acceleration.X);
Context.Result->SetNumberField(TEXT("accelerationY"), Acceleration.Y);
Context.Result->SetNumberField(TEXT("accelerationZ"), Acceleration.Z);
Context.Result->SetStringField(TEXT("message"), TEXT("Added acceleration force module."));
Context.SendSuccess(true, TEXT("Acceleration module added."));
return true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Parsed module inputs are never authored to the Niagara stack module.

Line 76/98/121 parse caller inputs, but Lines 88-90/107/129-132 only mirror those values into Context.Result; nothing writes them into the created module node. This makes the action claim configured values that were not actually applied.

Also applies to: 98-110, 115-135

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/McpAutomationBridge_NiagaraAuthoringHandlersParticleModules.cpp`
around lines 76 - 93, The parsed Acceleration values are never actually applied
to the Niagara module that was created. After the AddModuleAndVerify call
succeeds and the System reference is populated, you must author the parsed
Acceleration vector values (Acceleration.X, Acceleration.Y, Acceleration.Z) to
the actual module node in the Niagara stack. Currently, the code only copies
these values into Context.Result for the response, but the module itself remains
unconfigured. Add the necessary calls to apply these input parameters to the
created module node after the AddModuleAndVerify call and before setting
Context.Result values.

…color modules, stack-module readback

manage_effect Niagara module actions (add_spawn_rate_module, etc.) always failed EMITTER_NOT_FOUND:
the dispatch layer defaults emitterName to "DefaultEmitter" when omitted, but the C++ names the
emitter handle after the source emitter asset, so the exact-match lookup never hits.
add_emitter_to_system also ignored a caller-supplied emitterName, and add_acceleration/size/color_module
added User.MCP_* parameters instead of real stack modules; get_niagara_info reported no stack modules.

- LoadSystemAndEmitter: single-emitter fallback when the requested name isn't found and the system
  has exactly one emitter (surfaces emitterResolvedBy/resolvedEmitterName); still errors for 0 or >1.
- AddEmitterToSystem: honor caller emitterName via FNiagaraEmitterHandle::SetName.
- AddAcceleration/Size/Color: real modules via AddModuleToEmitterStack (AccelerationForce /
  ScaleSpriteSize / Color) instead of User.MCP_* parameter shims.
- AddModuleAndVerify: return CREATE_FAILED + false when the stack insertion yields a null module
  node, instead of a success response with moduleAdded:false.
- get_niagara_info: enumerate per-emitter stack modules (UNiagaraNodeFunctionCall::GetCalledUsage()
  == Module; GetOrderedModuleNodes is not DLL-exported).

Verified live in UE 5.8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@SoloGorilla SoloGorilla force-pushed the fix/niagara-emitter-and-modules branch from 7178c3a to b0cc8e5 Compare June 17, 2026 12:30
@SoloGorilla

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Addressed the success-on-failure finding: AddModuleAndVerify now sends CREATE_FAILED and returns false when AddModuleToEmitterStack yields a null node, instead of a success response with moduleAdded:false (pushed).

On "parsed inputs are never authored to the module": that is intentional for now. It matches the existing AddForceModule/AddVelocityModule pattern in this same file — they also add the module with engine defaults and echo the requested value without writing it into the stack. Authoring per-module input pins is a worthwhile enhancement, but it should cover force/velocity too for consistency; deferring to a focused follow-up rather than diverging only these three handlers here.

@SoloGorilla

Copy link
Copy Markdown
Contributor Author

Status of both review findings:

  1. Success-on-failure — fixed and pushed: AddModuleAndVerify now returns false and sends CREATE_FAILED when AddModuleToEmitterStack yields a null node, so the accel/size/color handlers no longer emit a success response with moduleAdded:false.
  2. Parsed inputs not authored to the module — intentionally out of scope here, as discussed above: it matches the existing AddForceModule/AddVelocityModule pattern in this same file (add module with engine defaults, echo requested values). Authoring per-module inputs is a worthwhile enhancement but should cover force/velocity too for consistency — deferring to a focused follow-up rather than diverging only these three handlers.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -t f "McpAutomationBridge_NiagaraAuthoringHandlersParticleModules.cpp" | head
FILE=$(fd -t f "McpAutomationBridge_NiagaraAuthoringHandlersParticleModules.cpp")
ast-grep run --pattern 'AddModuleAndVerify($$$) {
  $$$
}' --lang cpp "$FILE" 2>/dev/null | head -100
echo "---"
rg -n "CREATE_FAILED|AddModuleToEmitterStack|moduleAdded" "$FILE" -C2

Length of output: 1250


Confirmed — the fix is in place: AddModuleAndVerify (Line 18-26) now checks bModuleAdded and returns false with a CREATE_FAILED error when AddModuleToEmitterStack returns null, before any dirty/verify flow runs. This matches what you described.

On the input-authoring scope decision, that's a reasonable call — keeping the accel/size/color handlers consistent with the existing AddForceModule/AddVelocityModule pattern in this same file avoids introducing divergent behavior mid-PR, and a follow-up PR covering all module types together makes sense.

Kicking off a fresh review now to confirm everything looks good end-to-end.


✏️ Learnings added
Learnt from: SoloGorilla
URL: https://github.com/ChiR24/Unreal_mcp/pull/480

Timestamp: 2026-07-06T14:33:59.051Z
Learning: In plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/NiagaraAuthoring/, the AddForceModule and AddVelocityModule handlers (and now AddAccelerationModule/AddSizeModule/AddColorModule) intentionally add Niagara stack modules with engine defaults and echo requested parameter values in the response without authoring them as input pins on the module. This is an established pattern; any future enhancement to author per-module input pins should be applied consistently across all these module handlers rather than only new ones, and is deferred to a dedicated follow-up PR.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ChiR24 ChiR24 merged commit 5d8a2ff into ChiR24:dev Jul 7, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants