🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
using System;
|
[FEATURE]: Manage VFX function (#520)
Feature: Add ManageVFX
Add ManageVFX to the current function, support:
1. Modify LineRender, TrailRender properties
2. Modify particle system (legacy) properties
3. Modify VisualEffectGraph and use templates (does not support edit graph yet)
* Update Server/src/services/tools/utils.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update Server/src/services/tools/manage_vfx.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update ManageVFX.cs
Added 6 helper methods :
ApplyCommonRendererProperties - Handles shadows, lighting, probes, sorting, rendering layer (used by ParticleSetRenderer, LineSetProperties, TrailSetProperties)
GetCommonRendererInfo - Returns common renderer info for GetInfo methods
ApplyWidthProperties - Generic width handling (used by LineSetWidth, TrailSetWidth)
ApplyColorProperties - Generic color handling with fadeEndAlpha option (used by LineSetColor, TrailSetColor)
SetRendererMaterial - Generic material assignment (used by LineSetMaterial, TrailSetMaterial)
ApplyLineTrailProperties - Shared Line/Trail properties like alignment, textureMode, numCornerVertices (used by LineSetProperties, TrailSetProperties)
* Optimize the code structure
Declutter the redundant files by adding RendererHelpers and VectorParsing.cs
* Minor Fixes
Minor Fixes based on AI-feedback
* Fixes
---------
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-01-07 14:47:32 +08:00
|
|
|
using System.Collections.Generic;
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace MCPForUnity.Editor.Helpers
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
[FEATURE]: Manage VFX function (#520)
Feature: Add ManageVFX
Add ManageVFX to the current function, support:
1. Modify LineRender, TrailRender properties
2. Modify particle system (legacy) properties
3. Modify VisualEffectGraph and use templates (does not support edit graph yet)
* Update Server/src/services/tools/utils.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update Server/src/services/tools/manage_vfx.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update ManageVFX.cs
Added 6 helper methods :
ApplyCommonRendererProperties - Handles shadows, lighting, probes, sorting, rendering layer (used by ParticleSetRenderer, LineSetProperties, TrailSetProperties)
GetCommonRendererInfo - Returns common renderer info for GetInfo methods
ApplyWidthProperties - Generic width handling (used by LineSetWidth, TrailSetWidth)
ApplyColorProperties - Generic color handling with fadeEndAlpha option (used by LineSetColor, TrailSetColor)
SetRendererMaterial - Generic material assignment (used by LineSetMaterial, TrailSetMaterial)
ApplyLineTrailProperties - Shared Line/Trail properties like alignment, textureMode, numCornerVertices (used by LineSetProperties, TrailSetProperties)
* Optimize the code structure
Declutter the redundant files by adding RendererHelpers and VectorParsing.cs
* Minor Fixes
Minor Fixes based on AI-feedback
* Fixes
---------
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-01-07 14:47:32 +08:00
|
|
|
/// Utility class for parsing JSON tokens into Unity vector, math, and animation types.
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
/// Supports both array format [x, y, z] and object format {x: 1, y: 2, z: 3}.
|
[FEATURE]: Manage VFX function (#520)
Feature: Add ManageVFX
Add ManageVFX to the current function, support:
1. Modify LineRender, TrailRender properties
2. Modify particle system (legacy) properties
3. Modify VisualEffectGraph and use templates (does not support edit graph yet)
* Update Server/src/services/tools/utils.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update Server/src/services/tools/manage_vfx.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update ManageVFX.cs
Added 6 helper methods :
ApplyCommonRendererProperties - Handles shadows, lighting, probes, sorting, rendering layer (used by ParticleSetRenderer, LineSetProperties, TrailSetProperties)
GetCommonRendererInfo - Returns common renderer info for GetInfo methods
ApplyWidthProperties - Generic width handling (used by LineSetWidth, TrailSetWidth)
ApplyColorProperties - Generic color handling with fadeEndAlpha option (used by LineSetColor, TrailSetColor)
SetRendererMaterial - Generic material assignment (used by LineSetMaterial, TrailSetMaterial)
ApplyLineTrailProperties - Shared Line/Trail properties like alignment, textureMode, numCornerVertices (used by LineSetProperties, TrailSetProperties)
* Optimize the code structure
Declutter the redundant files by adding RendererHelpers and VectorParsing.cs
* Minor Fixes
Minor Fixes based on AI-feedback
* Fixes
---------
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-01-07 14:47:32 +08:00
|
|
|
/// </summary>
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
public static class VectorParsing
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken (array or object) into a Vector3.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed Vector3 or null if parsing fails</returns>
|
|
|
|
|
public static Vector3? ParseVector3(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Array format: [x, y, z]
|
|
|
|
|
if (token is JArray array && array.Count >= 3)
|
|
|
|
|
{
|
|
|
|
|
return new Vector3(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object format: {x: 1, y: 2, z: 3}
|
|
|
|
|
if (token is JObject obj && obj.ContainsKey("x") && obj.ContainsKey("y") && obj.ContainsKey("z"))
|
|
|
|
|
{
|
|
|
|
|
return new Vector3(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>(),
|
|
|
|
|
obj["z"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-07 13:33:20 +08:00
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Vector3 from '{token}': {ex.Message}");
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Vector3, returning a default value if parsing fails.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Vector3 ParseVector3OrDefault(JToken token, Vector3 defaultValue = default)
|
|
|
|
|
{
|
|
|
|
|
return ParseVector3(token) ?? defaultValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken (array or object) into a Vector2.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed Vector2 or null if parsing fails</returns>
|
|
|
|
|
public static Vector2? ParseVector2(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Array format: [x, y]
|
|
|
|
|
if (token is JArray array && array.Count >= 2)
|
|
|
|
|
{
|
|
|
|
|
return new Vector2(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object format: {x: 1, y: 2}
|
|
|
|
|
if (token is JObject obj && obj.ContainsKey("x") && obj.ContainsKey("y"))
|
|
|
|
|
{
|
|
|
|
|
return new Vector2(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-07 13:33:20 +08:00
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Vector2 from '{token}': {ex.Message}");
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
Harden `manage_scriptable_object` Tool (#522)
* feat(manage_scriptable_object): harden tool with path normalization, auto-resize, bulk mapping
Phase 1: Path Syntax & Auto-Resizing
- Add NormalizePropertyPath() to convert field[index] to Array.data format
- Add EnsureArrayCapacity() to auto-grow arrays when targeting out-of-bounds indices
Phase 2: Consolidation
- Replace duplicate TryGet* helpers with ParamCoercion/VectorParsing shared utilities
- Add Vector4 parsing support to VectorParsing.cs
Phase 3: Bulk Data Mapping
- Handle JArray values for list/array properties (recursive element setting)
- Handle JObject values for nested struct/class properties
Phase 4: Enhanced Reference Resolution
- Support plain 32-char GUID strings for ObjectReference fields
Phase 5: Validation & Dry-Run
- Add ValidatePatches() for pre-validation of all patches
- Add dry_run parameter to validate without mutating
Includes comprehensive stress test suite covering:
- Big Bang (large nested arrays), Out of Bounds, Friendly Path Syntax
- Deep Nesting, Mixed References, Rapid Fire, Type Mismatch
- Bulk Array Mapping, GUID Shorthand, Dry Run validation
* feat: Add AnimationCurve and Quaternion support to manage_scriptable_object tool
- Implement TrySetAnimationCurve() supporting both {'keys': [...]} and direct [...] formats
* Support keyframe properties: time, value, inSlope, outSlope, weightedMode, inWeight, outWeight
* Gracefully default missing optional fields to 0
* Clear error messages for malformed structures
- Implement TrySetQuaternion() with 4 input formats:
* Euler array [x, y, z] - 3 elements interpreted as degrees
* Raw array [x, y, z, w] - 4 components
* Object format {x, y, z, w} - explicit components
* Explicit euler {euler: [x, y, z]} - labeled format
- Improve error handling:
* Null values: AnimationCurve→empty, Quaternion→identity
* Invalid inputs rejected with specific, actionable error messages
* Validate keyframe objects and array sizes
- Add comprehensive test coverage in ManageScriptableObjectStressTests.cs:
* AnimationCurve with keyframe array format
* AnimationCurve with direct array (no wrapper)
* Quaternion via Euler angles
* Quaternion via raw components
* Quaternion via object format
* Quaternion via explicit euler property
- Fix test file compilation issues:
* Replace undefined TestFolder with _runRoot
* Add System.IO using statement
* refactor: consolidate test utilities to eliminate duplication
- Add TestUtilities.cs with shared helpers:
- ToJObject() - consolidates 11 duplicates across test files
- EnsureFolder() - consolidates 2 duplicates
- WaitForUnityReady() - consolidates 2 duplicates
- FindFallbackShader() - consolidates shader chain duplicates
- SafeDeleteAsset() - helper for asset cleanup
- CleanupEmptyParentFolders() - standardizes TearDown cleanup
- Update 11 test files to use shared TestUtilities via 'using static'
- Standardize TearDown cleanup patterns across all test files
- Net reduction of ~40 lines while improving maintainability
* fix: add missing animCurve and rotation fields to ComplexStressSO
Add AnimationCurve and Quaternion fields required by Phase 6 stress tests.
2026-01-07 22:46:35 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken (array or object) into a Vector4.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed Vector4 or null if parsing fails</returns>
|
|
|
|
|
public static Vector4? ParseVector4(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Array format: [x, y, z, w]
|
|
|
|
|
if (token is JArray array && array.Count >= 4)
|
|
|
|
|
{
|
|
|
|
|
return new Vector4(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>(),
|
|
|
|
|
array[3].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object format: {x: 1, y: 2, z: 3, w: 4}
|
|
|
|
|
if (token is JObject obj && obj.ContainsKey("x") && obj.ContainsKey("y") &&
|
|
|
|
|
obj.ContainsKey("z") && obj.ContainsKey("w"))
|
|
|
|
|
{
|
|
|
|
|
return new Vector4(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>(),
|
|
|
|
|
obj["z"].ToObject<float>(),
|
|
|
|
|
obj["w"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogWarning($"[VectorParsing] Failed to parse Vector4 from '{token}': {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken (array or object) into a Quaternion.
|
|
|
|
|
/// Supports both euler angles [x, y, z] and quaternion components [x, y, z, w].
|
|
|
|
|
/// Note: Raw quaternion components are NOT normalized. Callers should normalize if needed
|
|
|
|
|
/// for operations like interpolation where non-unit quaternions cause issues.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <param name="asEulerAngles">If true, treats 3-element arrays as euler angles</param>
|
|
|
|
|
/// <returns>The parsed Quaternion or null if parsing fails</returns>
|
|
|
|
|
public static Quaternion? ParseQuaternion(JToken token, bool asEulerAngles = true)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (token is JArray array)
|
|
|
|
|
{
|
|
|
|
|
// Quaternion components: [x, y, z, w]
|
|
|
|
|
if (array.Count >= 4)
|
|
|
|
|
{
|
|
|
|
|
return new Quaternion(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>(),
|
|
|
|
|
array[3].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Euler angles: [x, y, z]
|
|
|
|
|
if (array.Count >= 3 && asEulerAngles)
|
|
|
|
|
{
|
|
|
|
|
return Quaternion.Euler(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object format: {x: 0, y: 0, z: 0, w: 1}
|
|
|
|
|
if (token is JObject obj)
|
|
|
|
|
{
|
|
|
|
|
if (obj.ContainsKey("x") && obj.ContainsKey("y") && obj.ContainsKey("z") && obj.ContainsKey("w"))
|
|
|
|
|
{
|
|
|
|
|
return new Quaternion(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>(),
|
|
|
|
|
obj["z"].ToObject<float>(),
|
|
|
|
|
obj["w"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Euler format in object: {x: 45, y: 90, z: 0} (as euler angles)
|
|
|
|
|
if (obj.ContainsKey("x") && obj.ContainsKey("y") && obj.ContainsKey("z") && asEulerAngles)
|
|
|
|
|
{
|
|
|
|
|
return Quaternion.Euler(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>(),
|
|
|
|
|
obj["z"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-07 13:33:20 +08:00
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Quaternion from '{token}': {ex.Message}");
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken (array or object) into a Color.
|
|
|
|
|
/// Supports both [r, g, b, a] and {r: 1, g: 1, b: 1, a: 1} formats.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed Color or null if parsing fails</returns>
|
|
|
|
|
public static Color? ParseColor(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Array format: [r, g, b, a] or [r, g, b]
|
|
|
|
|
if (token is JArray array)
|
|
|
|
|
{
|
|
|
|
|
if (array.Count >= 4)
|
|
|
|
|
{
|
|
|
|
|
return new Color(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>(),
|
|
|
|
|
array[3].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (array.Count >= 3)
|
|
|
|
|
{
|
|
|
|
|
return new Color(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>(),
|
|
|
|
|
1f // Default alpha
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object format: {r: 1, g: 1, b: 1, a: 1}
|
|
|
|
|
if (token is JObject obj && obj.ContainsKey("r") && obj.ContainsKey("g") && obj.ContainsKey("b"))
|
|
|
|
|
{
|
|
|
|
|
float a = obj.ContainsKey("a") ? obj["a"].ToObject<float>() : 1f;
|
|
|
|
|
return new Color(
|
|
|
|
|
obj["r"].ToObject<float>(),
|
|
|
|
|
obj["g"].ToObject<float>(),
|
|
|
|
|
obj["b"].ToObject<float>(),
|
|
|
|
|
a
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-07 13:33:20 +08:00
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Color from '{token}': {ex.Message}");
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
[FEATURE]: Manage VFX function (#520)
Feature: Add ManageVFX
Add ManageVFX to the current function, support:
1. Modify LineRender, TrailRender properties
2. Modify particle system (legacy) properties
3. Modify VisualEffectGraph and use templates (does not support edit graph yet)
* Update Server/src/services/tools/utils.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update Server/src/services/tools/manage_vfx.py
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
* Update ManageVFX.cs
Added 6 helper methods :
ApplyCommonRendererProperties - Handles shadows, lighting, probes, sorting, rendering layer (used by ParticleSetRenderer, LineSetProperties, TrailSetProperties)
GetCommonRendererInfo - Returns common renderer info for GetInfo methods
ApplyWidthProperties - Generic width handling (used by LineSetWidth, TrailSetWidth)
ApplyColorProperties - Generic color handling with fadeEndAlpha option (used by LineSetColor, TrailSetColor)
SetRendererMaterial - Generic material assignment (used by LineSetMaterial, TrailSetMaterial)
ApplyLineTrailProperties - Shared Line/Trail properties like alignment, textureMode, numCornerVertices (used by LineSetProperties, TrailSetProperties)
* Optimize the code structure
Declutter the redundant files by adding RendererHelpers and VectorParsing.cs
* Minor Fixes
Minor Fixes based on AI-feedback
* Fixes
---------
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-01-07 14:47:32 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Color, returning a default value if parsing fails.
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Color ParseColorOrDefault(JToken token, Color defaultValue = default)
|
|
|
|
|
{
|
|
|
|
|
if (defaultValue == default) defaultValue = Color.black;
|
|
|
|
|
return ParseColor(token) ?? defaultValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken (array or object) into a Vector4.
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed Vector4 or null if parsing fails</returns>
|
|
|
|
|
public static Vector4? ParseVector4(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Array format: [x, y, z, w]
|
|
|
|
|
if (token is JArray array && array.Count >= 4)
|
|
|
|
|
{
|
|
|
|
|
return new Vector4(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>(),
|
|
|
|
|
array[3].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object format: {x: 1, y: 2, z: 3, w: 4}
|
|
|
|
|
if (token is JObject obj && obj.ContainsKey("x") && obj.ContainsKey("y") && obj.ContainsKey("z") && obj.ContainsKey("w"))
|
|
|
|
|
{
|
|
|
|
|
return new Vector4(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>(),
|
|
|
|
|
obj["z"].ToObject<float>(),
|
|
|
|
|
obj["w"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Vector4 from '{token}': {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Vector4, returning a default value if parsing fails.
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Vector4 ParseVector4OrDefault(JToken token, Vector4 defaultValue = default)
|
|
|
|
|
{
|
|
|
|
|
return ParseVector4(token) ?? defaultValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Gradient.
|
|
|
|
|
/// Supports formats:
|
|
|
|
|
/// - Simple: {startColor: [r,g,b,a], endColor: [r,g,b,a]}
|
|
|
|
|
/// - Full: {colorKeys: [{color: [r,g,b,a], time: 0.0}, ...], alphaKeys: [{alpha: 1.0, time: 0.0}, ...]}
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed Gradient or null if parsing fails</returns>
|
|
|
|
|
public static Gradient ParseGradient(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Gradient gradient = new Gradient();
|
|
|
|
|
|
|
|
|
|
if (token is JObject obj)
|
|
|
|
|
{
|
|
|
|
|
// Simple format: {startColor: ..., endColor: ...}
|
|
|
|
|
if (obj.ContainsKey("startColor"))
|
|
|
|
|
{
|
|
|
|
|
Color startColor = ParseColorOrDefault(obj["startColor"]);
|
|
|
|
|
Color endColor = ParseColorOrDefault(obj["endColor"] ?? obj["startColor"]);
|
|
|
|
|
float startAlpha = obj["startAlpha"]?.ToObject<float>() ?? startColor.a;
|
|
|
|
|
float endAlpha = obj["endAlpha"]?.ToObject<float>() ?? endColor.a;
|
|
|
|
|
|
|
|
|
|
gradient.SetKeys(
|
|
|
|
|
new GradientColorKey[] { new GradientColorKey(startColor, 0f), new GradientColorKey(endColor, 1f) },
|
|
|
|
|
new GradientAlphaKey[] { new GradientAlphaKey(startAlpha, 0f), new GradientAlphaKey(endAlpha, 1f) }
|
|
|
|
|
);
|
|
|
|
|
return gradient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Full format: {colorKeys: [...], alphaKeys: [...]}
|
|
|
|
|
var colorKeys = new List<GradientColorKey>();
|
|
|
|
|
var alphaKeys = new List<GradientAlphaKey>();
|
|
|
|
|
|
|
|
|
|
if (obj["colorKeys"] is JArray colorKeysArr)
|
|
|
|
|
{
|
|
|
|
|
foreach (var key in colorKeysArr)
|
|
|
|
|
{
|
|
|
|
|
Color color = ParseColorOrDefault(key["color"]);
|
|
|
|
|
float time = key["time"]?.ToObject<float>() ?? 0f;
|
|
|
|
|
colorKeys.Add(new GradientColorKey(color, time));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (obj["alphaKeys"] is JArray alphaKeysArr)
|
|
|
|
|
{
|
|
|
|
|
foreach (var key in alphaKeysArr)
|
|
|
|
|
{
|
|
|
|
|
float alpha = key["alpha"]?.ToObject<float>() ?? 1f;
|
|
|
|
|
float time = key["time"]?.ToObject<float>() ?? 0f;
|
|
|
|
|
alphaKeys.Add(new GradientAlphaKey(alpha, time));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure at least 2 keys
|
|
|
|
|
if (colorKeys.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
colorKeys.Add(new GradientColorKey(Color.white, 0f));
|
|
|
|
|
colorKeys.Add(new GradientColorKey(Color.white, 1f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (alphaKeys.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
alphaKeys.Add(new GradientAlphaKey(1f, 0f));
|
|
|
|
|
alphaKeys.Add(new GradientAlphaKey(1f, 1f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gradient.SetKeys(colorKeys.ToArray(), alphaKeys.ToArray());
|
|
|
|
|
return gradient;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Gradient from '{token}': {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Gradient, returning a default gradient if parsing fails.
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Gradient ParseGradientOrDefault(JToken token)
|
|
|
|
|
{
|
|
|
|
|
var result = ParseGradient(token);
|
|
|
|
|
if (result != null) return result;
|
|
|
|
|
|
|
|
|
|
// Return default white gradient
|
|
|
|
|
var gradient = new Gradient();
|
|
|
|
|
gradient.SetKeys(
|
|
|
|
|
new GradientColorKey[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
|
|
|
|
|
new GradientAlphaKey[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) }
|
|
|
|
|
);
|
|
|
|
|
return gradient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into an AnimationCurve.
|
|
|
|
|
/// Supports formats:
|
|
|
|
|
/// - Constant: 1.0 (number)
|
|
|
|
|
/// - Simple: {start: 0.0, end: 1.0}
|
|
|
|
|
/// - Full: {keys: [{time: 0.0, value: 1.0, inTangent: 0.0, outTangent: 0.0}, ...]}
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <returns>The parsed AnimationCurve or null if parsing fails</returns>
|
|
|
|
|
public static AnimationCurve ParseAnimationCurve(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Constant value: just a number
|
|
|
|
|
if (token.Type == JTokenType.Float || token.Type == JTokenType.Integer)
|
|
|
|
|
{
|
|
|
|
|
return AnimationCurve.Constant(0f, 1f, token.ToObject<float>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (token is JObject obj)
|
|
|
|
|
{
|
|
|
|
|
// Full format: {keys: [...]}
|
|
|
|
|
if (obj["keys"] is JArray keys)
|
|
|
|
|
{
|
|
|
|
|
AnimationCurve curve = new AnimationCurve();
|
|
|
|
|
foreach (var key in keys)
|
|
|
|
|
{
|
|
|
|
|
float time = key["time"]?.ToObject<float>() ?? 0f;
|
|
|
|
|
float value = key["value"]?.ToObject<float>() ?? 1f;
|
|
|
|
|
float inTangent = key["inTangent"]?.ToObject<float>() ?? 0f;
|
|
|
|
|
float outTangent = key["outTangent"]?.ToObject<float>() ?? 0f;
|
|
|
|
|
curve.AddKey(new Keyframe(time, value, inTangent, outTangent));
|
|
|
|
|
}
|
|
|
|
|
return curve;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Simple format: {start: 0.0, end: 1.0} or {startValue: 0.0, endValue: 1.0}
|
|
|
|
|
if (obj.ContainsKey("start") || obj.ContainsKey("startValue") || obj.ContainsKey("end") || obj.ContainsKey("endValue"))
|
|
|
|
|
{
|
|
|
|
|
float startValue = obj["start"]?.ToObject<float>() ?? obj["startValue"]?.ToObject<float>() ?? 1f;
|
|
|
|
|
float endValue = obj["end"]?.ToObject<float>() ?? obj["endValue"]?.ToObject<float>() ?? 1f;
|
|
|
|
|
AnimationCurve curve = new AnimationCurve();
|
|
|
|
|
curve.AddKey(0f, startValue);
|
|
|
|
|
curve.AddKey(1f, endValue);
|
|
|
|
|
return curve;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse AnimationCurve from '{token}': {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into an AnimationCurve, returning a constant curve if parsing fails.
|
|
|
|
|
/// Added for ManageVFX refactoring.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to parse</param>
|
|
|
|
|
/// <param name="defaultValue">The constant value for the default curve</param>
|
|
|
|
|
public static AnimationCurve ParseAnimationCurveOrDefault(JToken token, float defaultValue = 1f)
|
|
|
|
|
{
|
|
|
|
|
return ParseAnimationCurve(token) ?? AnimationCurve.Constant(0f, 1f, defaultValue);
|
|
|
|
|
}
|
|
|
|
|
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Rect.
|
|
|
|
|
/// Supports {x, y, width, height} format.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Rect? ParseRect(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (token is JObject obj &&
|
|
|
|
|
obj.ContainsKey("x") && obj.ContainsKey("y") &&
|
|
|
|
|
obj.ContainsKey("width") && obj.ContainsKey("height"))
|
|
|
|
|
{
|
|
|
|
|
return new Rect(
|
|
|
|
|
obj["x"].ToObject<float>(),
|
|
|
|
|
obj["y"].ToObject<float>(),
|
|
|
|
|
obj["width"].ToObject<float>(),
|
|
|
|
|
obj["height"].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Array format: [x, y, width, height]
|
|
|
|
|
if (token is JArray array && array.Count >= 4)
|
|
|
|
|
{
|
|
|
|
|
return new Rect(
|
|
|
|
|
array[0].ToObject<float>(),
|
|
|
|
|
array[1].ToObject<float>(),
|
|
|
|
|
array[2].ToObject<float>(),
|
|
|
|
|
array[3].ToObject<float>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-07 13:33:20 +08:00
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Rect from '{token}': {ex.Message}");
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a JToken into a Bounds.
|
|
|
|
|
/// Supports {center: {x,y,z}, size: {x,y,z}} format.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Bounds? ParseBounds(JToken token)
|
|
|
|
|
{
|
|
|
|
|
if (token == null || token.Type == JTokenType.Null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (token is JObject obj && obj.ContainsKey("center") && obj.ContainsKey("size"))
|
|
|
|
|
{
|
|
|
|
|
var center = ParseVector3(obj["center"]) ?? Vector3.zero;
|
|
|
|
|
var size = ParseVector3(obj["size"]) ?? Vector3.zero;
|
|
|
|
|
return new Bounds(center, size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-07 13:33:20 +08:00
|
|
|
McpLog.Warn($"[VectorParsing] Failed to parse Bounds from '{token}': {ex.Message}");
|
🎮 GameObject Toolset Redesign and Streamlining (#518)
* feat: Redesign GameObject API for better LLM ergonomics
## New Tools
- find_gameobjects: Search GameObjects, returns paginated instance IDs only
- manage_components: Component lifecycle (add, remove, set_property)
## New Resources
- unity://scene/gameobject/{id}: Single GameObject data (no component serialization)
- unity://scene/gameobject/{id}/components: All components (paginated)
- unity://scene/gameobject/{id}/component/{name}: Single component by type
## Updated
- manage_scene get_hierarchy: Now includes componentTypes array
- manage_gameobject: Slimmed to lifecycle only (create, modify, delete)
- Legacy actions (find, get_components, etc.) log deprecation warnings
## Extracted Utilities
- ParamCoercion: Centralized int/bool/float/string coercion
- VectorParsing: Vector3/Vector2/Quaternion/Color parsing
- GameObjectLookup: Centralized GameObject search logic
## Test Coverage
- 76 new Unity EditMode tests for ManageGameObject actions
- 21 new pytest tests for Python tools/resources
- New NL/T CI suite for GameObject API (GO-0 to GO-5)
Addresses LLM confusion with parameter overload by splitting into
focused tools and read-only resources.
* feat: Add static gameobject_api helper resource for UI discoverability
Adds unity://scene/gameobject-api resource that:
- Shows in Cursor's resource list UI (no parameters needed)
- Documents the parameterized gameobject resources
- Explains the workflow: find_gameobjects → read resource
- Lists examples and related tools
* feat: Add GO tests to main NL/T CI workflow
- Adds GO pass (GO-0 to GO-5) after T pass in claude-nl-suite.yml
- Includes retry logic for incomplete GO tests
- Updates all regex patterns to recognize GO-* test IDs
- Updates DESIRED lists to include all 21 tests (NL-0..4, T-A..J, GO-0..5)
- Updates default_titles for GO tests in markdown summary
- Keeps separate claude-gameobject-suite.yml for standalone runs
* feat: Add GameObject API stress tests and NL/T suite updates
Stress Tests (12 new tests):
- BulkCreate small/medium batches
- FindGameObjects pagination with by_component search
- AddComponents to single object
- GetComponents with full serialization
- SetComponentProperties (complex Rigidbody)
- Deep hierarchy creation and path lookup
- GetHierarchy with large scenes
- Resource read performance tests
- RapidFire create-modify-delete cycles
NL/T Suite Updates:
- Added GO-0..GO-10 tests in nl-gameobject-suite.md
- Fixed tool naming: mcp__unity__ → mcp__UnityMCP__
Other:
- Fixed LongUnityScriptClaudeTest.cs compilation errors
- Added reports/, .claude/local/, scripts/local-test/ to .gitignore
All 254 EditMode tests pass (250 run, 4 explicit skips)
* fix: Address code review feedback
- ParamCoercion: Use CultureInfo.InvariantCulture for float parsing
- ManageComponents: Move Transform removal check before GetComponent
- ManageGameObjectFindTests: Use try-finally for LogAssert.ignoreFailingMessages
- VectorParsing: Document that quaternions are not auto-normalized
- gameobject.py: Prefix unused ctx parameter with underscore
* fix: Address additional code review feedback
- ManageComponents: Reuse GameObjectLookup.FindComponentType instead of duplicate
- ManageComponents: Log warnings when SetPropertiesOnComponent fails
- GameObjectLookup: Make FindComponentType public for reuse
- gameobject.py: Extract _normalize_response helper to reduce duplication
- gameobject.py: Add TODO comment for unused typed response classes
* fix: Address more code review feedback
NL/T Prompt Fixes:
- nl-gameobject-suite.md: Remove non-existent list_resources/read_resource from AllowedTools
- nl-gameobject-suite.md: Fix parameter names (component_type, properties)
- nl-unity-suite-nl.md: Remove unused manage_editor from AllowedTools
Test Fixes:
- GameObjectAPIStressTests: Add null check to ToJObject helper
- GameObjectAPIStressTests: Clarify AudioSource usage comment
- ManageGameObjectFindTests: Use built-in 'UI' layer instead of 'Water'
- LongUnityScriptClaudeTest: Clean up NL/T test artifacts (Counte42 typo, HasTarget)
* docs: Add documentation for API limitations and behaviors
- GameObjectLookup.SearchByPath: Document and warn that includeInactive
has no effect (Unity API limitation)
- ManageComponents.TrySetProperty: Document case-insensitive lookup behavior
* More test fixes and tighten parameters on python tools
* fix: Align test expectation with implementation error message case
* docs: update README tools and resources lists
- Add missing tools: manage_components, batch_execute, find_gameobjects, refresh_unity
- Add missing resources: gameobject_api, editor_state_v2
- Make descriptions more concise across all tools and resources
- Ensure documentation matches current MCP server functionality
* fix: Address code review feedback
- ParamCoercion: Use InvariantCulture for int/double parsing consistency
- ManageComponents: Remove redundant Undo.RecordObject (AddComponent handles undo)
- ManageScene: Replace deprecated FindObjectsOfType with FindObjectsByType
- GameObjectLookup: Add explanatory comment to empty catch block
- gameobject.py: Extract _validate_instance_id helper to reduce duplication
- Tests: Fix assertion for instanceID (Unity IDs can be negative)
* chore: Remove accidentally committed test artifacts
- Remove Materials folder (40 .mat files from interactive testing)
- Remove Shaders folder (5 noise shaders from testing)
- Remove test scripts (Bounce*, CylinderBounce* from testing)
- Remove Temp.meta and commit.sh
* test: Improve delete tests to verify actual deletion
- Delete_ByTag_DeletesMatchingObjects: Verify objects are actually destroyed
- Delete_ByLayer_DeletesMatchingObjects: Assert deletion using Unity null check
- Delete_MultipleObjectsSameName_DeletesCorrectly: Document first-match behavior
- Delete_Success_ReturnsDeletedCount: Verify count value if present
All tests now verify deletion occurred rather than just checking for a result.
* refactor: remove deprecated manage_gameobject actions
- Remove deprecated switch cases: find, get_components, get_component, add_component, remove_component, set_component_property
- Remove deprecated wrapper methods (423 lines deleted from ManageGameObject.cs)
- Delete ManageGameObjectFindTests.cs (tests deprecated 'find' action)
- Remove deprecated test methods from ManageGameObjectTests.cs
- Add GameObject resource URIs to README documentation
- Add batch_execute performance tips to README, tool description, and gameobject_api resource
- Enhance batch_execute description to emphasize 10-100x performance gains
Total: ~1200 lines removed. New API (find_gameobjects, manage_components, resources) is the recommended path forward.
* fix: Remove starlette stubs from conftest.py
Starlette is now a proper dependency via the mcp package, so we don't need
to stub it anymore. The real package handles all HTTP transport needs.
2026-01-07 02:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|