Skip to content

[fixes] Fixes and Skill upload#707

Merged
Scriptwonder merged 1 commit intoCoplayDev:betafrom
Scriptwonder:someFixesDuringUsage
Feb 10, 2026
Merged

[fixes] Fixes and Skill upload#707
Scriptwonder merged 1 commit intoCoplayDev:betafrom
Scriptwonder:someFixesDuringUsage

Conversation

@Scriptwonder
Copy link
Collaborator

@Scriptwonder Scriptwonder commented Feb 10, 2026

Description

  1. Some fixes I made during a very comprehensive scene generation, including fixing VFX generating magenta due to a lack of a renderer material
  2. I put the skills right in the .claude now, so us (developers who actually pull this repo) can directly use it. I still keep the skills under the parent folder in case users wants to download it.

Type of Change

Save your change type

  • Bug fix (non-breaking change that fixes an issue)
  • Refactoring (no functional changes)
  • Test update

Changes Made

  1. Add Skill in .Claude Folder
  2. Add better VFX handling
  3. Add Helper better error message

Testing/Screenshots/Recordings

Documentation Updates

  • I have added/removed/modified tools or resources
  • If yes, I have updated all documentation files using:
    • The LLM prompt at tools/UPDATE_DOCS_PROMPT.md (recommended)
    • Manual updates following the guide at tools/UPDATE_DOCS.md

Related Issues

Additional Notes

Summary by Sourcery

Improve Unity VFX particle creation robustness, enhance component and renderer error handling, and embed Unity MCP skill documentation for local development use.

New Features:

  • Add a particle_create action to the Unity VFX management pipeline to create or prepare ParticleSystem components with sensible defaults and valid renderer materials.
  • Add a Unity MCP skill bundle under the .claude folder, including operator guide and detailed tools/workflow reference for working with Unity via MCP.

Bug Fixes:

  • Ensure particle system renderers automatically receive valid, supported materials instead of falling back to invalid shaders that render magenta.

Enhancements:

  • Improve component addition helpers to detect duplicate components that disallow multiple instances and return clearer error messages.
  • Extend VFX management metadata and Python-side tooling to recognize the new particle_create action and expose it through the manage_vfx service.

Tests:

  • Add a unit test to verify that the manage_vfx service correctly accepts and forwards the new particle_create action to Unity.

Summary by CodeRabbit

Release Notes

  • New Features

    • Particle system creation now available with configurable playback settings
    • Component duplication prevention for restricted component types with clear error messages
  • Bug Fixes

    • Improved material validation detecting invalid shaders with diagnostic warnings
    • Enhanced error messaging for component restrictions
  • Documentation

    • Added comprehensive skill guide with quick start and best practices
    • Tools reference guide with usage examples for all MCP actions
    • Workflow patterns for setup, scene creation, scripting, asset management, and debugging

1. Some fixes I made during a very comprehensive scene generation, including VFX generating magenta due to lack of renderer material
2. I put the skills right in the .claude now, so us (developers who actually pull this repo) can directly use it. I still keep the skills under the parent folder in case users wants to download it.
Copilot AI review requested due to automatic review settings February 10, 2026 05:30
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 10, 2026

Reviewer's Guide

Adds a new particle_create action and Unity-side implementation with safer renderer material handling, improves component-add error messages for disallowed multiples, wires the new VFX action through the MCP server with a regression test, and introduces in-repo Unity MCP skill/reference docs under .claude/ for developers.

Sequence diagram for new particle_create VFX workflow

sequenceDiagram
    actor DevClient
    participant MCPServer as MCPServer_manage_vfx_py
    participant UnityBridge as Unity_MCP_Server
    participant ManageVFX as ManageVFX
    participant ParticleControl as ParticleControl
    participant RendererHelpers as RendererHelpers

    DevClient->>MCPServer: call manage_vfx(tool="manage_vfx", action="particle_create", params)
    MCPServer->>UnityBridge: send tool request manage_vfx action="particle_create"
    UnityBridge->>ManageVFX: HandleParticleSystemAction(@params, action="create")
    ManageVFX->>ParticleControl: Create(@params)

    ParticleControl->>ParticleControl: FindTargetGameObject(@params)
    alt GameObject not found
        ParticleControl->>ParticleControl: new GameObject(objectName)
        ParticleControl->>ParticleControl: Undo.RegisterCreatedObjectUndo(go, "Create objectName")
    end

    ParticleControl->>ParticleControl: Apply position/rotation/scale via ManageVfxCommon

    ParticleControl->>ParticleControl: GetComponent(ParticleSystem)
    alt ParticleSystem missing
        ParticleControl->>ParticleControl: AddComponent(ParticleSystem)
    end

    ParticleControl->>ParticleControl: GetComponent(ParticleSystemRenderer)
    alt Renderer exists
        ParticleControl->>RendererHelpers: EnsureMaterial(renderer)
        RendererHelpers->>RendererHelpers: IsUsableMaterial(existingMaterial)
        alt Material invalid or missing
            RendererHelpers->>RendererHelpers: Determine VFXComponentType
            RendererHelpers->>RendererHelpers: GetDefaultVFXMaterial(componentType)
            RendererHelpers->>RendererHelpers: Undo.RecordObject(renderer)
            RendererHelpers->>RendererHelpers: Assign defaultMat to renderer.sharedMaterial
            RendererHelpers-->>ParticleControl: return
        else Material valid
            RendererHelpers-->>ParticleControl: return
        end
    end

    ParticleControl->>ParticleControl: Configure main module (playOnAwake, loop)
    ParticleControl->>ParticleControl: EditorUtility.SetDirty(go)
    ParticleControl->>ParticleControl: MarkSceneDirty(activeScene)

    ParticleControl-->>ManageVFX: { success, message, target, targetId, createdGameObject, addedParticleSystem, assignedMaterial }
    ManageVFX-->>UnityBridge: wrap as particle_create result
    UnityBridge-->>MCPServer: return tool result
    MCPServer-->>DevClient: respond with particle_create outcome
Loading

Class diagram for updated VFX and component helper utilities

classDiagram
    class ManageVFX {
        <<static>>
        -HandleParticleSystemAction(@params, action)
    }

    class ParticleControl {
        <<static>>
        +Create(@params) object
        +EnableModule(@params) object
        %% other particle control methods unchanged
    }

    class RendererHelpers {
        <<static>>
        +EnsureMaterial(renderer Renderer) void
        -IsUsableMaterial(material Material) bool
        +ApplyCommonRendererProperties(renderer Renderer) void
    }

    class ComponentOps {
        <<static>>
        +AddComponent(target GameObject, componentType Type, error out string) Component
        -ApplyDefaultValues(component Component) void
        -AllowsMultiple(target GameObject, componentType Type) bool
    }

    class GameObjectComponentHelpers {
        <<static>>
        +AddComponentInternal(targetGo GameObject, typeName string, searchMethod string) object
        +RemoveComponentInternal(targetGo GameObject, typeName string) object
        -AllowsMultiple(componentType Type) bool
    }

    ManageVFX ..> ParticleControl : uses
    ParticleControl ..> RendererHelpers : uses EnsureMaterial

    ComponentOps ..> GameObject : operates_on
    GameObjectComponentHelpers ..> GameObject : operates_on

    ComponentOps ..> Component : creates
    GameObjectComponentHelpers ..> Component : creates

    RendererHelpers ..> Renderer : configures
    Renderer <|-- ParticleSystemRenderer

    note for ComponentOps "Improved error messages when component already exists and DisallowMultipleComponent prevents duplicates"
    note for GameObjectComponentHelpers "Uses AllowsMultiple to prevent adding disallowed duplicate components and returns clearer ErrorResponse messages"
Loading

File-Level Changes

Change Details Files
Add particle_create action to create/prepare ParticleSystems with sane defaults and valid renderer materials.
  • Implement ParticleControl.Create to resolve/create target GameObjects, add/configure ParticleSystem components, apply transform properties, and ensure a valid renderer material is assigned.
  • Track and return metadata about whether a GameObject or ParticleSystem was newly created and which material was assigned.
  • Wire the new create action into ManageVFX.HandleParticleSystemAction and expose it in the documented particle_* action list.
  • Expose particle_create in the Python manage_vfx PARTICLE_ACTIONS list used by the MCP server.
MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs
MCPForUnity/Editor/Tools/Vfx/ManageVFX.cs
Server/src/services/tools/manage_vfx.py
Harden renderer material assignment to avoid magenta/invalid VFX materials and log when replacing bad materials.
  • Change RendererHelpers.EnsureMaterial to treat null or invalid materials as unusable and replace them with default VFX materials.
  • Add IsUsableMaterial helper that rejects null shaders, InternalErrorShader, and unsupported shaders.
  • Log a warning when replacing an existing invalid VFX material and ensure Undo/SetDirty are correctly ordered around material assignment.
MCPForUnity/Editor/Helpers/RendererHelpers.cs
Improve error reporting when adding components that disallow multiple instances via both generic helper paths.
  • In ComponentOps.AddComponent, pre-check for existing components that do not allow multiples, returning a clear error instead of a generic failure.
  • Adjust the failure path after Undo.AddComponent to detect the duplicate-component case and emit a more specific error message when Unity rejects the add.
  • Introduce an AllowsMultiple helper that respects the DisallowMultipleComponent attribute.
  • Mirror the clearer duplicate-component handling in GameObjectComponentHelpers.AddComponentInternal with its own AllowsMultiple check.
MCPForUnity/Editor/Helpers/ComponentOps.cs
MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs
Add MCP server test coverage to ensure manage_vfx correctly forwards the new particle_create action to Unity.
  • Add a pytest that stubs Unity instance resolution and send_with_unity_instance to validate routing and parameter passing for particle_create.
  • Verify that manage_vfx returns a success response and preserves action/target/properties in the forwarded params.
Server/tests/test_manage_vfx_actions.py
Check in Unity MCP skill and reference documentation under .claude for direct use by developers.
  • Add a Unity-MCP workflow patterns reference covering setup, scenes, scripts, assets, testing, debugging, batch operations, and error recovery.
  • Add a detailed Unity-MCP tools reference enumerating all tools, parameters, and usage examples.
  • Add a SKILL.md operator guide describing best practices, core tool categories, and common workflows, optimized for use as a Claude skill.
  • Place all new docs under .claude/skills/unity-mcp-skill so they are available to local developers while keeping original user-facing copies under the parent folder.
.claude/skills/unity-mcp-skill/references/workflows.md
.claude/skills/unity-mcp-skill/references/tools-reference.md
.claude/skills/unity-mcp-skill/SKILL.md

Possibly linked issues

  • #0: The PR implements the requested Unity MCP Claude skill with refresh_unity, batch_execute, and schema-focused documentation.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Adds comprehensive skill documentation for unity-mcp-orchestrator, implements duplicate-component prevention across helper classes, enhances material validation in renderers, and introduces a new particle creation action to the VFX toolchain with corresponding server-side support and tests.

Changes

Cohort / File(s) Summary
Documentation & Skills
.claude/skills/unity-mcp-skill/SKILL.md, .claude/skills/unity-mcp-skill/references/tools-reference.md, .claude/skills/unity-mcp-skill/references/workflows.md
Adds comprehensive skill guides covering orchestration patterns, tool reference documentation with signatures and examples, and detailed workflow examples for scene creation, script development, asset management, testing, and error recovery.
Component Addition Safeguards
MCPForUnity/Editor/Helpers/ComponentOps.cs, MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs
Introduces duplicate-component prevention logic with AllowsMultiple helper to check DisallowMultipleComponent attribute; prevents adding multiple instances where disallowed and provides consistent error messaging in both pre-add checks and failure paths.
Material Validation
MCPForUnity/Editor/Helpers/RendererHelpers.cs
Adds IsUsableMaterial helper to validate material presence, shader existence, and shader integrity; enhances EnsureMaterial to log warnings when existing materials are invalid and defers dirty-marking until after default material assignment.
Particle Creation Feature
MCPForUnity/Editor/Tools/Vfx/ManageVFX.cs, MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs, Server/src/services/tools/manage_vfx.py
Adds new particle_create action routing; implements ParticleControl.Create method handling target location/creation, position/rotation/scale setup, ParticleSystem configuration, and material assignment; updates server-side action constants.
VFX Action Testing
Server/tests/test_manage_vfx_actions.py
Adds unit test validating particle_create action dispatch with mocked dependencies, parameter extraction, and end-to-end behavior verification.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Server as Server<br/>(manage_vfx)
    participant Unity as Unity Editor<br/>(ManageVFX)
    participant ParticleControl
    participant GameObjectOps
    participant RendererHelpers

    Client->>Server: particle_create action<br/>(target, position, rotation, etc.)
    Server->>Unity: send_with_unity_instance<br/>(particle_create params)
    Unity->>ManageVFX: HandleParticleSystemAction<br/>("create")
    ManageVFX->>ParticleControl: ParticleControl.Create(params)
    
    ParticleControl->>GameObjectOps: Locate or create<br/>target GameObject
    GameObjectOps-->>ParticleControl: GameObject reference
    
    ParticleControl->>ParticleControl: Apply position,<br/>rotation, scale
    ParticleControl->>ParticleControl: Ensure ParticleSystem<br/>component exists
    
    ParticleControl->>RendererHelpers: EnsureMaterial<br/>(renderer)
    RendererHelpers->>RendererHelpers: Validate existing material<br/>via IsUsableMaterial
    RendererHelpers-->>ParticleControl: Material assigned/<br/>validated
    
    ParticleControl->>ParticleControl: Configure playOnAwake,<br/>loop settings
    ParticleControl->>ParticleControl: Mark GameObject &<br/>scene dirty
    
    ParticleControl-->>Unity: Result object<br/>(success, details)
    Unity-->>Server: Response payload
    Server-->>Client: Success response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #659: Adds the same skill documentation files (SKILL.md, tools-reference.md, workflows.md) for unity-mcp, indicating parallel documentation efforts.
  • PR #626: Modifies VFX toolchain components (ParticleControl, ManageVFX, RendererHelpers) with related material handling and action routing changes.
  • PR #520: Introduces foundational ManageVFX and manage_vfx functionality that this PR directly extends with the particle_create action.

Poem

🐰 Hop, skip, and a particle spark—
Particles spring to life in the editor's dark,
No duplicates allowed on this garden so fair,
Materials bloom valid, with validation and care!
From server to shader, workflows take flight,
A cotton-tail symphony of creation done right!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and generic, using non-descriptive terms like 'Fixes' without specifying what was fixed, making it unclear what the primary changes are. Revise the title to be more specific about the main changes, such as 'Add particle creation to VFX tools and embed Unity MCP skill documentation'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The PR description covers most required template sections (Description, Type of Change, Changes Made), but the Documentation Updates checkboxes are unchecked despite significant documentation additions in .claude/skills.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@Scriptwonder Scriptwonder changed the title Fixes and Skill upload [fixes] Fixes and Skill upload Feb 10, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The new AllowsMultiple logic is now duplicated between ComponentOps and GameObjectComponentHelpers; consider centralizing this into a shared helper to keep the rules for multi-instance components consistent over time.
  • In ComponentOps.AddComponent the AllowsMultiple(GameObject target, Type componentType) signature takes a GameObject that isn’t used beyond a null check; you could simplify this API (or actually use the target) to make the intent clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `AllowsMultiple` logic is now duplicated between `ComponentOps` and `GameObjectComponentHelpers`; consider centralizing this into a shared helper to keep the rules for multi-instance components consistent over time.
- In `ComponentOps.AddComponent` the `AllowsMultiple(GameObject target, Type componentType)` signature takes a `GameObject` that isn’t used beyond a null check; you could simplify this API (or actually use the target) to make the intent clearer.

## Individual Comments

### Comment 1
<location> `MCPForUnity/Editor/Helpers/ComponentOps.cs:363-372` </location>
<code_context>
             }
         }
+
+        private static bool AllowsMultiple(GameObject target, Type componentType)
+        {
+            if (target == null || componentType == null)
+            {
+                return false;
+            }
+
+            if (Attribute.IsDefined(componentType, typeof(DisallowMultipleComponent), inherit: true))
+            {
+                return false;
+            }
+
+            return true;
+        }
     }
</code_context>

<issue_to_address>
**nitpick:** The `target` parameter in `AllowsMultiple` is unused and could be removed or leveraged.

This helper ignores the `GameObject target` and only checks `DisallowMultipleComponent`. Consider either removing `target` to simplify the API, or using it to handle Unity’s built-in single-instance components (e.g., Transform-like types) so the pre-check and error messages are more accurate.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +363 to +372
private static bool AllowsMultiple(GameObject target, Type componentType)
{
if (target == null || componentType == null)
{
return false;
}

if (Attribute.IsDefined(componentType, typeof(DisallowMultipleComponent), inherit: true))
{
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: The target parameter in AllowsMultiple is unused and could be removed or leveraged.

This helper ignores the GameObject target and only checks DisallowMultipleComponent. Consider either removing target to simplify the API, or using it to handle Unity’s built-in single-instance components (e.g., Transform-like types) so the pre-check and error messages are more accurate.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In @.claude/skills/unity-mcp-skill/references/tools-reference.md:
- Around line 5-15: Add a new "VFX Tools" section to the tools-reference that
documents the manage_vfx tool and its actions; include the action prefixes
particle_ (e.g., particle_create), vfx_, line_, and trail_, list key parameters
for each common action (spawn settings, lifetime, emissionRate, prefab/template
id, position/rotation/scale, parent, attachBone, color/gradient,
velocity/spread, duration, loop, and any resource keys), and show which actions
are handled by the manage_vfx tool (e.g., particle_create, particle_update,
vfx_play, vfx_stop, line_draw, trail_emit). Reference the manage_vfx tool name
and the particle_create action so reviewers can locate and verify the new doc
entry.

In @.claude/skills/unity-mcp-skill/references/workflows.md:
- Around line 581-589: The retry loop using read_resource (variables
max_retries, attempt, editor_state) currently uses a bare except: which also
catches SystemExit/KeyboardInterrupt; change it to catch only Exception (e.g.,
except Exception:) and preserve the exponential backoff sleep behavior so only
runtime errors are retried while allowing interrupts/termination to propagate.

In `@MCPForUnity/Editor/Helpers/ComponentOps.cs`:
- Around line 363-376: Remove the unused GameObject target parameter from the
private static AllowsMultiple method in ComponentOps.cs and simplify its body to
only check the DisallowMultipleComponent attribute on the passed-in Type; update
every call site that currently passes a GameObject + Type to invoke the new
signature AllowsMultiple(Type componentType) instead, and remove the obsolete
null-check for target; note there is a duplicate method AllowsMultiple(Type) in
GameObjectComponentHelpers.cs but only change ComponentOps.cs as requested.

In `@MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs`:
- Around line 54-59: When adding a ParticleSystem to an existing GameObject, use
the Unity Undo API so the operation is undoable: replace the direct call to
go.AddComponent<ParticleSystem>() with Undo.AddComponent<ParticleSystem>(go)
when createdGameObject is false (or generally when not creating the GameObject).
Update the block that sets ps and addedParticleSystem (the variables ps,
addedParticleSystem and the logic that checks createdGameObject) so the
ParticleSystem is created via Undo.AddComponent when appropriate, preserving
addedParticleSystem semantics.
🧹 Nitpick comments (3)
Server/tests/test_manage_vfx_actions.py (1)

12-16: Prefix unused send_fn with _ to silence lint warning.

The Ruff ARG001 warning flags the unused send_fn parameter. Since the mock must match the real signature, prefixing it is the idiomatic fix.

🔧 Proposed fix
-    async def fake_send_with_unity_instance(send_fn, unity_instance, tool_name, params):
+    async def fake_send_with_unity_instance(_send_fn, unity_instance, tool_name, params):
MCPForUnity/Editor/Helpers/RendererHelpers.cs (1)

53-62: Consider logging when no default material could be found.

When componentType is null (unsupported renderer type) or GetOrCreateDefaultVFXMaterial returns null, the method silently leaves the broken material in place. A warning here would help diagnose cases where the fallback also fails.

Proposed improvement
             if (componentType.HasValue)
             {
                 Material defaultMat = RenderPipelineUtility.GetOrCreateDefaultVFXMaterial(componentType.Value);
                 if (defaultMat != null)
                 {
                     Undo.RecordObject(renderer, "Assign default VFX material");
                     renderer.sharedMaterial = defaultMat;
                     EditorUtility.SetDirty(renderer);
                 }
+                else
+                {
+                    McpLog.Warn($"[RendererHelpers] Could not find or create a default VFX material for {componentType.Value}.");
+                }
+            }
+            else
+            {
+                McpLog.Warn($"[RendererHelpers] Unsupported renderer type '{renderer.GetType().Name}', cannot assign default material.");
             }
MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs (1)

101-109: Consider consolidating AllowsMultiple with ComponentOps.AllowsMultiple to avoid drift.

Both GameObjectComponentHelpers.AllowsMultiple(Type componentType) (lines 101-109) and ComponentOps.AllowsMultiple(GameObject target, Type componentType) contain equivalent logic—they both check for the DisallowMultipleComponent attribute. The GameObject parameter in ComponentOps is only used for a null guard and doesn't affect the core attribute check. A single shared implementation would eliminate duplicate logic and reduce maintenance risk.

Comment on lines +5 to +15
## Table of Contents

- [Infrastructure Tools](#infrastructure-tools)
- [Scene Tools](#scene-tools)
- [GameObject Tools](#gameobject-tools)
- [Script Tools](#script-tools)
- [Asset Tools](#asset-tools)
- [Material & Shader Tools](#material--shader-tools)
- [Editor Control Tools](#editor-control-tools)
- [Testing Tools](#testing-tools)

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

manage_vfx tool is missing from this reference.

This PR adds the particle_create action and the VFX tool is a significant part of the toolchain, yet there's no VFX Tools section in this reference document. Consider adding a section covering manage_vfx with its action prefixes (particle_*, vfx_*, line_*, trail_*) and key parameters.

🤖 Prompt for AI Agents
In @.claude/skills/unity-mcp-skill/references/tools-reference.md around lines 5
- 15, Add a new "VFX Tools" section to the tools-reference that documents the
manage_vfx tool and its actions; include the action prefixes particle_ (e.g.,
particle_create), vfx_, line_, and trail_, list key parameters for each common
action (spawn settings, lifetime, emissionRate, prefab/template id,
position/rotation/scale, parent, attachBone, color/gradient, velocity/spread,
duration, loop, and any resource keys), and show which actions are handled by
the manage_vfx tool (e.g., particle_create, particle_update, vfx_play, vfx_stop,
line_draw, trail_emit). Reference the manage_vfx tool name and the
particle_create action so reviewers can locate and verify the new doc entry.

Comment on lines +581 to +589
max_retries = 5
for attempt in range(max_retries):
try:
editor_state = read_resource("mcpforunity://editor/state")
if editor_state["ready_for_tools"]:
break
except:
time.sleep(2 ** attempt) # Exponential backoff
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Bare except: in example code — prefer except Exception:.

Users may copy-paste this pattern. A bare except: catches KeyboardInterrupt and SystemExit, which is rarely intended.

📝 Suggested fix
-    except:
+    except Exception:
         time.sleep(2 ** attempt)  # Exponential backoff
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
max_retries = 5
for attempt in range(max_retries):
try:
editor_state = read_resource("mcpforunity://editor/state")
if editor_state["ready_for_tools"]:
break
except:
time.sleep(2 ** attempt) # Exponential backoff
```
max_retries = 5
for attempt in range(max_retries):
try:
editor_state = read_resource("mcpforunity://editor/state")
if editor_state["ready_for_tools"]:
break
except Exception:
time.sleep(2 ** attempt) # Exponential backoff
🤖 Prompt for AI Agents
In @.claude/skills/unity-mcp-skill/references/workflows.md around lines 581 -
589, The retry loop using read_resource (variables max_retries, attempt,
editor_state) currently uses a bare except: which also catches
SystemExit/KeyboardInterrupt; change it to catch only Exception (e.g., except
Exception:) and preserve the exponential backoff sleep behavior so only runtime
errors are retried while allowing interrupts/termination to propagate.

Comment on lines +363 to +376
private static bool AllowsMultiple(GameObject target, Type componentType)
{
if (target == null || componentType == null)
{
return false;
}

if (Attribute.IsDefined(componentType, typeof(DisallowMultipleComponent), inherit: true))
{
return false;
}

return true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all AllowsMultiple method definitions
rg -n "AllowsMultiple" --type=cs -B2 -A10

Repository: CoplayDev/unity-mcp

Length of output: 7603


Remove unused target parameter.

The target parameter is never used in the method logic—it's only null-checked. All call sites (lines 56, 67) already access target immediately before calling AllowsMultiple, making the null guard redundant. Remove the parameter and simplify the method.

Note: GameObjectComponentHelpers.cs contains an identical AllowsMultiple(Type componentType) method (line 101), indicating duplicated logic. However, both implementations are private static, so consolidation would require refactoring the access levels. At minimum, remove the unused parameter here.

🤖 Prompt for AI Agents
In `@MCPForUnity/Editor/Helpers/ComponentOps.cs` around lines 363 - 376, Remove
the unused GameObject target parameter from the private static AllowsMultiple
method in ComponentOps.cs and simplify its body to only check the
DisallowMultipleComponent attribute on the passed-in Type; update every call
site that currently passes a GameObject + Type to invoke the new signature
AllowsMultiple(Type componentType) instead, and remove the obsolete null-check
for target; note there is a duplicate method AllowsMultiple(Type) in
GameObjectComponentHelpers.cs but only change ComponentOps.cs as requested.

Comment on lines +54 to +59
var ps = go.GetComponent<ParticleSystem>();
if (ps == null)
{
ps = go.AddComponent<ParticleSystem>();
addedParticleSystem = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use Undo.AddComponent for undo-safe ParticleSystem addition.

When the target GameObject already exists (createdGameObject == false), calling go.AddComponent<ParticleSystem>() bypasses the Undo system. The user won't be able to Ctrl+Z the component addition on a pre-existing object.

Proposed fix
             var ps = go.GetComponent<ParticleSystem>();
             if (ps == null)
             {
-                ps = go.AddComponent<ParticleSystem>();
+                if (!EditorApplication.isPlaying)
+                {
+                    ps = Undo.AddComponent<ParticleSystem>(go);
+                }
+                else
+                {
+                    ps = go.AddComponent<ParticleSystem>();
+                }
                 addedParticleSystem = true;
             }
🤖 Prompt for AI Agents
In `@MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs` around lines 54 - 59, When
adding a ParticleSystem to an existing GameObject, use the Unity Undo API so the
operation is undoable: replace the direct call to
go.AddComponent<ParticleSystem>() with Undo.AddComponent<ParticleSystem>(go)
when createdGameObject is false (or generally when not creating the GameObject).
Update the block that sets ps and addedParticleSystem (the variables ps,
addedParticleSystem and the logic that checks createdGameObject) so the
ParticleSystem is created via Undo.AddComponent when appropriate, preserving
addedParticleSystem semantics.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new particle_create action to the cross-language manage_vfx toolchain (Python server → Unity Editor tool) to create/prepare ParticleSystems and avoid magenta VFX by ensuring a valid renderer material, plus improves component-add error messages and vendors Unity-MCP “skill” documentation into .claude/.

Changes:

  • Add particle_create to the server-side manage_vfx action allowlist and a Python unit test verifying request forwarding.
  • Implement Unity-side particle_create handling (create/prepare ParticleSystem, set transform, ensure renderer material) and update action docs/routing.
  • Improve Unity component-add error messaging when adding disallowed duplicate components; add .claude skill reference docs.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Server/src/services/tools/manage_vfx.py Adds particle_create to valid action list so server accepts/forwards it.
Server/tests/test_manage_vfx_actions.py New unit test confirming particle_create params are forwarded to Unity transport.
MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs Implements ParticleControl.Create() to prepare/create ParticleSystem and ensure renderer material.
MCPForUnity/Editor/Tools/Vfx/ManageVFX.cs Documents and routes particle_createcreate handler; includes it in “valid actions” error text.
MCPForUnity/Editor/Helpers/RendererHelpers.cs Enhances material validation and replaces invalid/unsupported materials to avoid magenta rendering.
MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs Adds clearer error when adding non-multi components that already exist.
MCPForUnity/Editor/Helpers/ComponentOps.cs Mirrors improved duplicate-component error messaging for low-level helper.
.claude/skills/unity-mcp-skill/SKILL.md Adds Unity-MCP operator skill documentation into .claude.
.claude/skills/unity-mcp-skill/references/tools-reference.md Adds tool reference documentation for Unity-MCP usage.
.claude/skills/unity-mcp-skill/references/workflows.md Adds workflow examples/patterns for Unity-MCP usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

var ps = go.GetComponent<ParticleSystem>();
if (ps == null)
{
ps = go.AddComponent<ParticleSystem>();
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

particle_create uses go.AddComponent<ParticleSystem>(), which bypasses Unity's Undo system in edit mode (unlike other tools here that use Undo.AddComponent). Consider using Undo.AddComponent when !EditorApplication.isPlaying (and falling back to AddComponent in play mode) so the operation can be undone/redone and matches existing component-add patterns.

Suggested change
ps = go.AddComponent<ParticleSystem>();
if (!EditorApplication.isPlaying)
{
ps = Undo.AddComponent<ParticleSystem>(go);
}
else
{
ps = go.AddComponent<ParticleSystem>();
}

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +33
if (go == null)
{
string objectName = target;
int slashIndex = target.LastIndexOf('/');
if (slashIndex >= 0 && slashIndex < target.Length - 1)
{
objectName = target.Substring(slashIndex + 1);
}

go = new GameObject(objectName);
createdGameObject = true;
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

When the target GameObject cannot be resolved, particle_create always creates a new GameObject named from target. If callers use searchMethod=by_id and the id is missing/invalid, this will create a GameObject named like an instance id, which is likely unintended. Consider only auto-creating when the lookup mode is name/path (or when searchMethod is unset), and returning an explicit error for by_id (and potentially by_tag/by_layer) when no match is found.

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +52
if (@params["position"] != null)
{
go.transform.position = ManageVfxCommon.ParseVector3(@params["position"]);
}
if (@params["rotation"] != null)
{
go.transform.eulerAngles = ManageVfxCommon.ParseVector3(@params["rotation"]);
}
if (@params["scale"] != null)
{
go.transform.localScale = ManageVfxCommon.ParseVector3(@params["scale"]);
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

particle_create mutates the target Transform (position/rotation/scale) without recording Undo. In edit mode this makes the operation non-undoable even though other VFX write operations call Undo.RecordObject. Consider calling Undo.RecordObject(go.transform, ...) (and/or Undo.RecordObject(go, ...)) before applying transform changes when !EditorApplication.isPlaying.

Copilot uses AI. Check for mistakes.
return false;
}

return !Attribute.IsDefined(componentType, typeof(DisallowMultipleComponent), inherit: true);
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

There are now two separate AllowsMultiple implementations (here and in ComponentOps). This duplicates the logic for interpreting [DisallowMultipleComponent] and can drift over time. Consider extracting a shared helper (e.g., in ComponentOps or a common utility) and reusing it in both places.

Suggested change
return !Attribute.IsDefined(componentType, typeof(DisallowMultipleComponent), inherit: true);
return ComponentOps.AllowsMultiple(componentType);

Copilot uses AI. Check for mistakes.
Comment on lines +67 to +74
if (target.GetComponent(componentType) != null && !AllowsMultiple(target, componentType))
{
error = $"Component '{componentType.Name}' already exists on '{target.name}' and this type does not allow multiple instances.";
}
else
{
error = $"Failed to add component '{componentType.Name}' to '{target.name}'. Unity may restrict this component on the current target.";
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better.

Suggested change
if (target.GetComponent(componentType) != null && !AllowsMultiple(target, componentType))
{
error = $"Component '{componentType.Name}' already exists on '{target.name}' and this type does not allow multiple instances.";
}
else
{
error = $"Failed to add component '{componentType.Name}' to '{target.name}'. Unity may restrict this component on the current target.";
}
error = target.GetComponent(componentType) != null && !AllowsMultiple(target, componentType)
? $"Component '{componentType.Name}' already exists on '{target.name}' and this type does not allow multiple instances."
: $"Failed to add component '{componentType.Name}' to '{target.name}'. Unity may restrict this component on the current target.";

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +75
if (@params["playOnAwake"] != null)
{
main.playOnAwake = @params["playOnAwake"].ToObject<bool>();
}
else
{
main.playOnAwake = false;
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better.

Copilot uses AI. Check for mistakes.
@Scriptwonder Scriptwonder merged commit 1bb0734 into CoplayDev:beta Feb 10, 2026
9 checks passed
@Scriptwonder Scriptwonder deleted the someFixesDuringUsage branch February 10, 2026 05:37
msanatan pushed a commit to msanatan/unity-mcp that referenced this pull request Feb 10, 2026
1. Some fixes I made during a very comprehensive scene generation, including VFX generating magenta due to lack of renderer material
2. I put the skills right in the .claude now, so us (developers who actually pull this repo) can directly use it. I still keep the skills under the parent folder in case users wants to download it.
msanatan pushed a commit to msanatan/unity-mcp that referenced this pull request Feb 25, 2026
1. Some fixes I made during a very comprehensive scene generation, including VFX generating magenta due to lack of renderer material
2. I put the skills right in the .claude now, so us (developers who actually pull this repo) can directly use it. I still keep the skills under the parent folder in case users wants to download it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants