chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:49:17 +08:00
commit 7243d5823b
2201 changed files with 257291 additions and 0 deletions
+282
View File
@@ -0,0 +1,282 @@
---
name: unity-mcp-orchestrator
description: Orchestrate Unity Editor via MCP (Model Context Protocol) tools and resources. Use when working with Unity projects through MCP for Unity - creating/modifying GameObjects, editing scripts, managing scenes, running tests, or any Unity Editor automation. Provides best practices, tool schemas, and workflow patterns for effective Unity-MCP integration.
---
# Unity-MCP Operator Guide
This skill helps you effectively use the Unity Editor with MCP tools and resources.
## Template Notice
Examples in `references/workflows.md` and `references/tools-reference.md` are reusable templates. They may be inaccurate across Unity versions, package setups (UGUI/TMP/Input System), and project-specific conventions. Please check console, compilation errors, or use screenshot after implementation.
Before applying a template:
- Validate targets/components first via resources and `find_gameobjects`.
- Treat names, enum values, and property payloads as placeholders to adapt.
## Quick Start: Resource-First Workflow
**Always read relevant resources before using tools.** This prevents errors and provides the necessary context.
```
1. Check editor state → mcpforunity://editor/state
2. Understand the scene → mcpforunity://scene/gameobject-api
3. Find what you need → find_gameobjects or resources
4. Take action → tools (manage_gameobject, create_script, script_apply_edits, apply_text_edits, validate_script, delete_script, get_sha, etc.)
5. Verify results → read_console, manage_camera(action="screenshot"), resources
```
## Critical Best Practices
### 1. After Writing/Editing Scripts: Wait for Compilation and Check Console
```python
# After create_script or script_apply_edits:
# Both tools already trigger AssetDatabase.ImportAsset + RequestScriptCompilation automatically.
# No need to call refresh_unity — just wait for compilation to finish, then check console.
# 1. Poll editor state until compilation completes
# Read mcpforunity://editor/state → wait until is_compiling == false
# 2. Check for compilation errors
read_console(types=["error"], count=10, include_stacktrace=True)
```
**Why:** Unity must compile scripts before they're usable. `create_script` and `script_apply_edits` already trigger import and compilation automatically — calling `refresh_unity` afterward is redundant.
### 2. Use `batch_execute` for Multiple Operations
```python
# 10-100x faster than sequential calls
batch_execute(
commands=[
{"tool": "manage_gameobject", "params": {"action": "create", "name": "Cube1", "primitive_type": "Cube"}},
{"tool": "manage_gameobject", "params": {"action": "create", "name": "Cube2", "primitive_type": "Cube"}},
{"tool": "manage_gameobject", "params": {"action": "create", "name": "Cube3", "primitive_type": "Cube"}}
],
parallel=True # Hint only: Unity may still execute sequentially
)
```
**Max 25 commands per batch by default (configurable in Unity MCP Tools window, max 100).** Use `fail_fast=True` for dependent operations.
**Tip:** Also use `batch_execute` for discovery — batch multiple `find_gameobjects` calls instead of calling them one at a time:
```python
batch_execute(commands=[
{"tool": "find_gameobjects", "params": {"search_term": "Camera", "search_method": "by_component"}},
{"tool": "find_gameobjects", "params": {"search_term": "Player", "search_method": "by_tag"}},
{"tool": "find_gameobjects", "params": {"search_term": "GameManager", "search_method": "by_name"}}
])
```
### 3. Use Screenshots to Verify Visual Results
```python
# Basic screenshot (saves to Assets/, returns file path only)
manage_camera(action="screenshot")
# Inline screenshot (returns base64 PNG directly to the AI)
manage_camera(action="screenshot", include_image=True)
# Use a specific camera and cap resolution for smaller payloads
manage_camera(action="screenshot", camera="MainCamera", include_image=True, max_resolution=512)
# Batch surround: captures front/back/left/right/top/bird_eye around the scene
manage_camera(action="screenshot", batch="surround", max_resolution=256)
# Batch surround centered on a specific object
manage_camera(action="screenshot", batch="surround", view_target="Player", max_resolution=256)
# Positioned screenshot: place a temp camera and capture in one call
manage_camera(action="screenshot", view_target="Player", view_position=[0, 10, -10], max_resolution=512)
# Scene View screenshot: capture what the developer sees in the editor
manage_camera(action="screenshot", capture_source="scene_view", include_image=True)
# Scene View framed on a specific object
manage_camera(action="screenshot", capture_source="scene_view", view_target="Canvas", include_image=True)
```
**Best practices for AI scene understanding:**
- Use `include_image=True` when you need to *see* the scene, not just save a file.
- Use `batch="surround"` for a comprehensive overview (6 angles, one command).
- Use `view_target`/`view_position` to capture from a specific viewpoint without needing a scene camera.
- Use `capture_source="scene_view"` to see the editor viewport (gizmos, wireframes, grid).
- Keep `max_resolution` at 256512 to balance quality vs. token cost.
```python
# Agentic camera loop: point, shoot, analyze
manage_gameobject(action="look_at", target="MainCamera", look_at_target="Player")
manage_camera(action="screenshot", camera="MainCamera", include_image=True, max_resolution=512)
# → Analyze image, decide next action
# Multi-view screenshot (6-angle contact sheet)
manage_camera(action="screenshot_multiview", max_resolution=480)
# Scene View for editor-level inspection (shows gizmos, debug overlays, etc.)
manage_camera(action="screenshot", capture_source="scene_view", view_target="Player", include_image=True)
```
### 4. Check Console After Major Changes
```python
read_console(
action="get",
types=["error", "warning"], # Focus on problems
count=10,
format="detailed"
)
```
### 5. Always Check `editor_state` Before Complex Operations
```python
# Read mcpforunity://editor/state to check:
# - is_compiling: Wait if true
# - is_domain_reload_pending: Wait if true
# - ready_for_tools: Only proceed if true
# - blocking_reasons: Why tools might fail
```
## Parameter Type Conventions
These are common patterns, not strict guarantees. `manage_components.set_property` payload shapes can vary by component/property; if a template fails, inspect the component resource payload and adjust.
### Vectors (position, rotation, scale, color)
```python
# Both forms accepted:
position=[1.0, 2.0, 3.0] # List
position="[1.0, 2.0, 3.0]" # JSON string
```
### Booleans
```python
# Both forms accepted:
include_inactive=True # Boolean
include_inactive="true" # String
```
### Colors
```python
# Auto-detected format:
color=[255, 0, 0, 255] # 0-255 range
color=[1.0, 0.0, 0.0, 1.0] # 0.0-1.0 normalized (auto-converted)
```
### Paths
```python
# Assets-relative (default):
path="Assets/Scripts/MyScript.cs"
# URI forms:
uri="mcpforunity://path/Assets/Scripts/MyScript.cs"
uri="file:///full/path/to/file.cs"
```
## Core Tool Categories
| Category | Key Tools | Use For |
|----------|-----------|---------|
| **Scene** | `manage_scene`, `find_gameobjects` | Scene operations, finding objects |
| **Objects** | `manage_gameobject`, `manage_components` | Creating/modifying GameObjects |
| **Scripts** | `create_script`, `script_apply_edits`, `validate_script` | C# code management (auto-refreshes on create/edit) |
| **Assets** | `manage_asset`, `manage_prefabs` | Asset operations. **Prefab instantiation** is done via `manage_gameobject(action="create", prefab_path="...")`, not `manage_prefabs`. |
| **Editor** | `manage_editor`, `execute_menu_item`, `read_console` | Editor control, package deployment (`deploy_package`/`restore_package` actions) |
| **Testing** | `run_tests`, `get_test_job` | Unity Test Framework |
| **Batch** | `batch_execute` | Parallel/bulk operations |
| **Camera** | `manage_camera` | Camera management (Unity Camera + Cinemachine). **Tier 1** (always available): create, target, lens, priority, list, screenshot. **Tier 2** (requires `com.unity.cinemachine`): brain, body/aim/noise pipeline, extensions, blending, force/release. 7 presets: follow, third_person, freelook, dolly, static, top_down, side_scroller. Resource: `mcpforunity://scene/cameras`. Use `ping` to check Cinemachine availability. See [tools-reference.md](references/tools-reference.md#camera-tools). |
| **Graphics** | `manage_graphics` | Rendering and post-processing management. 33 actions across 5 groups: **Volume** (create/configure volumes and effects, URP/HDRP), **Bake** (lightmaps, light probes, reflection probes, Edit mode only), **Stats** (draw calls, batches, memory), **Pipeline** (quality levels, pipeline settings), **Features** (URP renderer features: add, remove, toggle, reorder). Resources: `mcpforunity://scene/volumes`, `mcpforunity://rendering/stats`, `mcpforunity://pipeline/renderer-features`. Use `ping` to check pipeline status. See [tools-reference.md](references/tools-reference.md#graphics-tools). |
| **Packages** | `manage_packages` | Install, remove, search, and manage Unity packages and scoped registries. Query actions: list installed, search registry, get info, ping, poll status. Mutating actions: add/remove packages, embed for editing, add/remove scoped registries, force resolve. Validates identifiers, warns on git URLs, checks dependents before removal (`force=true` to override). See [tools-reference.md](references/tools-reference.md#package-tools). |
| **Physics** | `manage_physics` | Manage 3D and 2D physics (21 actions). Settings, collision matrix, materials, joints (14 types). Queries: `raycast`, `raycast_all`, `linecast`, `shapecast` (sphere/box/capsule sweep), `overlap`. Forces: `apply_force` (AddForce/AddTorque/AddExplosionForce with ForceMode). Rigidbody: `get_rigidbody`, `configure_rigidbody` (mass, drag, gravity, constraints, collision detection). Validation: scene-wide checks. Simulation: `simulate_step` in edit mode. See [tools-reference.md](references/tools-reference.md#physics-tools). |
| **ProBuilder** | `manage_probuilder` | 3D modeling, mesh editing, complex geometry. **When `com.unity.probuilder` is installed, prefer ProBuilder shapes over primitive GameObjects** for editable geometry, multi-material faces, or complex shapes. Supports 12 shape types, face/edge/vertex editing, smoothing, and per-face materials. See [ProBuilder Guide](references/probuilder-guide.md). |
| **UI** | `manage_ui`, `batch_execute` with `manage_gameobject` + `manage_components` | **UI Toolkit**: Use `manage_ui` to create UXML/USS files, attach UIDocument, inspect visual trees. **uGUI (Canvas)**: Use `batch_execute` for Canvas, Panel, Button, Text, Slider, Toggle, Input Field. **Read `mcpforunity://project/info` first** to detect uGUI/TMP/Input System/UI Toolkit availability. (see [UI workflows](references/workflows.md#ui-creation-workflows)) |
| **Docs** | `unity_reflect`, `unity_docs` | API verification and documentation lookup. **`unity_reflect`** inspects live C# APIs via reflection (requires Unity connection): `search` types across assemblies, `get_type` for member summary, `get_member` for full signatures. **`unity_docs`** fetches official docs from docs.unity3d.com (no Unity connection needed): `get_doc` (ScriptReference), `get_manual` (Manual pages), `get_package_doc` (package docs), `lookup` (parallel search all sources + project assets). **Trust hierarchy: reflection > project assets > docs.** Workflow: `unity_reflect` search -> get_type -> get_member -> `unity_docs` lookup. See [tools-reference.md](references/tools-reference.md#docs-tools). |
## Common Workflows
### Creating a New Script and Using It
```python
# 1. Create the script (automatically triggers import + compilation)
create_script(
path="Assets/Scripts/PlayerController.cs",
contents="using UnityEngine;\n\npublic class PlayerController : MonoBehaviour\n{\n void Update() { }\n}"
)
# 2. Wait for compilation to finish
# Read mcpforunity://editor/state → wait until is_compiling == false
# 3. Check for compilation errors
read_console(types=["error"], count=10)
# 4. Only then attach to GameObject
manage_gameobject(action="modify", target="Player", components_to_add=["PlayerController"])
```
### Finding and Modifying GameObjects
```python
# 1. Find by name/tag/component (returns IDs only)
result = find_gameobjects(search_term="Enemy", search_method="by_tag", page_size=50)
# 2. Get full data via resource
# mcpforunity://scene/gameobject/{instance_id}
# 3. Modify using the ID
manage_gameobject(action="modify", target=instance_id, position=[10, 0, 0])
```
### Running and Monitoring Tests
```python
# 1. Start test run (async)
result = run_tests(mode="EditMode", test_names=["MyTests.TestSomething"])
job_id = result["job_id"]
# 2. Poll for completion
result = get_test_job(job_id=job_id, wait_timeout=60, include_failed_tests=True)
```
## Pagination Pattern
Large queries return paginated results. Always follow `next_cursor`:
```python
cursor = 0
all_items = []
while True:
result = manage_scene(action="get_hierarchy", page_size=50, cursor=cursor)
all_items.extend(result["data"]["items"])
if not result["data"].get("next_cursor"):
break
cursor = result["data"]["next_cursor"]
```
## Multi-Instance Workflow
When multiple Unity Editors are running:
```python
# 1. List instances via resource: mcpforunity://instances
# 2. Set active instance
set_active_instance(instance="MyProject@abc123")
# 3. All subsequent calls route to that instance
```
## Error Recovery
| Symptom | Cause | Solution |
|---------|-------|----------|
| Tools return "busy" | Compilation in progress | Wait, check `editor_state` |
| "stale_file" error | File changed since SHA | Re-fetch SHA with `get_sha`, retry |
| Connection lost | Domain reload | Wait ~5s, reconnect |
| Commands fail silently | Wrong instance | Check `set_active_instance` |
## Reference Files
For detailed schemas and examples:
- **[tools-reference.md](references/tools-reference.md)**: Complete tool documentation with all parameters
- **[resources-reference.md](references/resources-reference.md)**: All available resources and their data
- **[workflows.md](references/workflows.md)**: Extended workflow examples and patterns
@@ -0,0 +1,444 @@
# ProBuilder Workflow Guide
Patterns and best practices for AI-driven ProBuilder mesh editing through MCP for Unity.
## Availability
ProBuilder is an **optional** Unity package (`com.unity.probuilder`). Check `mcpforunity://project/info` or call `manage_probuilder(action="ping")` to verify it's installed before using any ProBuilder tools. If available, **prefer ProBuilder over primitive GameObjects** for any geometry that needs editing, multi-material faces, or non-trivial shapes.
## Core Workflow: Always Get Info First
Before any mesh edit, call `get_mesh_info` with `include='faces'` to understand the geometry:
```python
# Step 1: Get face info with directions
result = manage_probuilder(action="get_mesh_info", target="MyCube",
properties={"include": "faces"})
# Response includes per-face:
# index: 0, normal: [0, 1, 0], center: [0, 0.5, 0], direction: "top"
# index: 1, normal: [0, -1, 0], center: [0, -0.5, 0], direction: "bottom"
# index: 2, normal: [0, 0, 1], center: [0, 0, 0.5], direction: "front"
# ...
# Step 2: Use the direction labels to pick faces
# Want to extrude the top? Find the face with direction="top"
manage_probuilder(action="extrude_faces", target="MyCube",
properties={"faceIndices": [0], "distance": 1.5})
```
### Include Parameter
| Value | Returns | Use When |
|-------|---------|----------|
| `"summary"` | Counts, bounds, materials | Quick check / validation |
| `"faces"` | + normals, centers, directions | Selecting faces for editing |
| `"edges"` | + edge vertex pairs with world positions (max 200) | Edge-based operations |
| `"all"` | Everything | Full mesh analysis |
## Shape Creation
### All 12 Shape Types
```python
# Basic shapes
manage_probuilder(action="create_shape", properties={"shape_type": "Cube", "name": "MyCube"})
manage_probuilder(action="create_shape", properties={"shape_type": "Sphere", "name": "MySphere"})
manage_probuilder(action="create_shape", properties={"shape_type": "Cylinder", "name": "MyCyl"})
manage_probuilder(action="create_shape", properties={"shape_type": "Plane", "name": "MyPlane"})
manage_probuilder(action="create_shape", properties={"shape_type": "Cone", "name": "MyCone"})
manage_probuilder(action="create_shape", properties={"shape_type": "Prism", "name": "MyPrism"})
# Parametric shapes
manage_probuilder(action="create_shape", properties={
"shape_type": "Torus", "name": "MyTorus",
"rows": 16, "columns": 24, "innerRadius": 0.5, "outerRadius": 1.0
})
manage_probuilder(action="create_shape", properties={
"shape_type": "Pipe", "name": "MyPipe",
"radius": 1.0, "height": 2.0, "thickness": 0.2
})
manage_probuilder(action="create_shape", properties={
"shape_type": "Arch", "name": "MyArch",
"radius": 2.0, "angle": 180, "segments": 12
})
# Architectural shapes
manage_probuilder(action="create_shape", properties={
"shape_type": "Stair", "name": "MyStairs", "steps": 10
})
manage_probuilder(action="create_shape", properties={
"shape_type": "CurvedStair", "name": "Spiral", "steps": 12
})
manage_probuilder(action="create_shape", properties={
"shape_type": "Door", "name": "MyDoor"
})
# Custom polygon
manage_probuilder(action="create_poly_shape", properties={
"points": [[0,0,0], [5,0,0], [5,0,5], [2.5,0,7], [0,0,5]],
"extrudeHeight": 3.0, "name": "Pentagon"
})
```
## Common Editing Operations
### Extrude a Roof
```python
# 1. Create a building base
manage_probuilder(action="create_shape", properties={
"shape_type": "Cube", "name": "Building", "size": [4, 3, 6]
})
# 2. Find the top face
info = manage_probuilder(action="get_mesh_info", target="Building",
properties={"include": "faces"})
# Find face with direction="top" -> e.g. index 2
# 3. Extrude upward for a flat roof extension
manage_probuilder(action="extrude_faces", target="Building",
properties={"faceIndices": [2], "distance": 0.5})
```
### Cut a Hole (Delete Faces)
```python
# 1. Get face info
info = manage_probuilder(action="get_mesh_info", target="Wall",
properties={"include": "faces"})
# Find the face with direction="front" -> e.g. index 4
# 2. Subdivide to create more faces
manage_probuilder(action="subdivide", target="Wall",
properties={"faceIndices": [4]})
# 3. Get updated face info (indices changed after subdivide!)
info = manage_probuilder(action="get_mesh_info", target="Wall",
properties={"include": "faces"})
# 4. Delete the center face(s) for the hole
manage_probuilder(action="delete_faces", target="Wall",
properties={"faceIndices": [6]})
```
### Bevel Edges
```python
# Get edge info
info = manage_probuilder(action="get_mesh_info", target="MyCube",
properties={"include": "edges"})
# Bevel specific edges
manage_probuilder(action="bevel_edges", target="MyCube",
properties={"edgeIndices": [0, 1, 2, 3], "amount": 0.1})
```
### Detach Faces to New Object
```python
# Detach and keep original (default)
manage_probuilder(action="detach_faces", target="MyCube",
properties={"faceIndices": [0, 1], "deleteSourceFaces": False})
# Detach and remove from source
manage_probuilder(action="detach_faces", target="MyCube",
properties={"faceIndices": [0, 1], "deleteSourceFaces": True})
```
### Select Faces by Direction
```python
# Select all upward-facing faces
manage_probuilder(action="select_faces", target="MyMesh",
properties={"direction": "up", "tolerance": 0.7})
# Grow selection from a seed face
manage_probuilder(action="select_faces", target="MyMesh",
properties={"growFrom": [0], "growAngle": 45})
```
### Double-Sided Geometry
```python
# Create inside faces for a room (duplicate and flip normals)
manage_probuilder(action="duplicate_and_flip", target="Room",
properties={"faceIndices": [0, 1, 2, 3, 4, 5]})
```
### Create Polygon from Existing Vertices
```python
# Connect existing vertices into a new face (auto-finds winding order)
manage_probuilder(action="create_polygon", target="MyMesh",
properties={"vertexIndices": [0, 3, 7, 4]})
```
## Vertex Operations
```python
# Move vertices by offset
manage_probuilder(action="move_vertices", target="MyCube",
properties={"vertexIndices": [0, 1, 2, 3], "offset": [0, 1, 0]})
# Weld nearby vertices (proximity-based merge)
manage_probuilder(action="weld_vertices", target="MyCube",
properties={"vertexIndices": [0, 1, 2, 3], "radius": 0.1})
# Insert vertex on an edge
manage_probuilder(action="insert_vertex", target="MyCube",
properties={"edge": {"a": 0, "b": 1}, "point": [0.5, 0, 0]})
# Add evenly-spaced points along edges
manage_probuilder(action="append_vertices_to_edge", target="MyCube",
properties={"edgeIndices": [0, 1], "count": 3})
```
## Smoothing Workflow
### Auto-Smooth (Recommended Default)
```python
# Apply auto-smoothing with default 30 degree threshold
manage_probuilder(action="auto_smooth", target="MyMesh",
properties={"angleThreshold": 30})
```
- **Low angle (15-25)**: More hard edges, faceted look
- **Medium angle (30-45)**: Good default, smooth curves + sharp corners
- **High angle (60-80)**: Very smooth, only sharpest edges remain hard
### Manual Smoothing Groups
```python
# Set specific faces to smooth group 1
manage_probuilder(action="set_smoothing", target="MyMesh",
properties={"faceIndices": [0, 1, 2], "smoothingGroup": 1})
# Set other faces to hard edges (group 0)
manage_probuilder(action="set_smoothing", target="MyMesh",
properties={"faceIndices": [3, 4, 5], "smoothingGroup": 0})
```
## Mesh Cleanup Pattern
After editing, always clean up:
```python
# 1. Center the pivot (important after extrusions that shift geometry)
manage_probuilder(action="center_pivot", target="MyMesh")
# 2. Optionally freeze transform if you moved/rotated the object
manage_probuilder(action="freeze_transform", target="MyMesh")
# 3. Validate mesh health
result = manage_probuilder(action="validate_mesh", target="MyMesh")
# Check result.data.healthy -- if false, repair
# 4. Auto-repair if needed
manage_probuilder(action="repair_mesh", target="MyMesh")
```
## Building Complex Objects with ProBuilder
When ProBuilder is available, prefer it over primitive GameObjects for complex geometry. ProBuilder lets you create, edit, and combine shapes into detailed objects without external 3D tools.
### Example: Simple House
```python
# 1. Create base building
manage_probuilder(action="create_shape", properties={
"shape_type": "Cube", "name": "House", "width": 6, "height": 3, "depth": 8
})
# 2. Get face info to find the top face
info = manage_probuilder(action="get_mesh_info", target="House",
properties={"include": "faces"})
# Find direction="top" -> e.g. index 2
# 3. Extrude the top face to create a flat raised section
manage_probuilder(action="extrude_faces", target="House",
properties={"faceIndices": [2], "distance": 0.3})
# 4. Re-query faces, then move top vertices inward to form a ridge
info = manage_probuilder(action="get_mesh_info", target="House",
properties={"include": "faces"})
# Find the new top face after extrude, get its vertex indices
# Move them to form a peaked roof shape
manage_probuilder(action="move_vertices", target="House",
properties={"vertexIndices": [0, 1, 2, 3], "offset": [0, 2, 0]})
# 5. Cut a doorway: subdivide front face, delete center sub-face
info = manage_probuilder(action="get_mesh_info", target="House",
properties={"include": "faces"})
# Find direction="front", subdivide it
manage_probuilder(action="subdivide", target="House",
properties={"faceIndices": [4]})
# Re-query, find bottom-center face, delete it
info = manage_probuilder(action="get_mesh_info", target="House",
properties={"include": "faces"})
manage_probuilder(action="delete_faces", target="House",
properties={"faceIndices": [12]})
# 6. Add a door frame with arch
manage_probuilder(action="create_shape", properties={
"shape_type": "Door", "name": "Doorway",
"position": [0, 0, 4], "width": 1.5, "height": 2.5
})
# 7. Add stairs to the door
manage_probuilder(action="create_shape", properties={
"shape_type": "Stair", "name": "FrontSteps",
"position": [0, 0, 5], "steps": 3, "width": 2
})
# 8. Smooth organic parts, keep architectural edges sharp
manage_probuilder(action="auto_smooth", target="House",
properties={"angleThreshold": 30})
# 9. Assign materials per face
manage_probuilder(action="set_face_material", target="House",
properties={"faceIndices": [0, 1, 2, 3], "materialPath": "Assets/Materials/Brick.mat"})
manage_probuilder(action="set_face_material", target="House",
properties={"faceIndices": [4, 5], "materialPath": "Assets/Materials/Roof.mat"})
# 10. Cleanup
manage_probuilder(action="center_pivot", target="House")
manage_probuilder(action="validate_mesh", target="House")
```
### Example: Pillared Corridor (Batch)
```python
# Create multiple columns efficiently
batch_execute(commands=[
{"tool": "manage_probuilder", "params": {
"action": "create_shape",
"properties": {"shape_type": "Cylinder", "name": f"Pillar_{i}",
"radius": 0.3, "height": 4, "segments": 12,
"position": [i * 3, 0, 0]}
}} for i in range(6)
] + [
# Floor
{"tool": "manage_probuilder", "params": {
"action": "create_shape",
"properties": {"shape_type": "Plane", "name": "Floor",
"width": 18, "height": 6, "position": [7.5, 0, 0]}
}},
# Ceiling
{"tool": "manage_probuilder", "params": {
"action": "create_shape",
"properties": {"shape_type": "Plane", "name": "Ceiling",
"width": 18, "height": 6, "position": [7.5, 4, 0]}
}},
])
# Bevel all pillar tops for decoration
for i in range(6):
info = manage_probuilder(action="get_mesh_info", target=f"Pillar_{i}",
properties={"include": "edges"})
# Find top ring edges, bevel them
manage_probuilder(action="bevel_edges", target=f"Pillar_{i}",
properties={"edgeIndices": [0, 1, 2, 3], "amount": 0.05})
# Smooth the pillars
for i in range(6):
manage_probuilder(action="auto_smooth", target=f"Pillar_{i}",
properties={"angleThreshold": 45})
```
### Example: Custom L-Shaped Room
```python
# Use polygon shape for non-rectangular footprint
manage_probuilder(action="create_poly_shape", properties={
"points": [
[0, 0, 0], [10, 0, 0], [10, 0, 6],
[4, 0, 6], [4, 0, 10], [0, 0, 10]
],
"extrudeHeight": 3.0,
"name": "LRoom"
})
# Create inside faces for the room interior
info = manage_probuilder(action="get_mesh_info", target="LRoom",
properties={"include": "faces"})
# Duplicate and flip all faces to make interior visible
all_faces = list(range(info["data"]["faceCount"]))
manage_probuilder(action="duplicate_and_flip", target="LRoom",
properties={"faceIndices": all_faces})
# Cut a window: subdivide a wall face, delete center
# (follow the get_mesh_info -> subdivide -> get_mesh_info -> delete pattern)
```
### Example: Torus Knot / Decorative Ring
```python
# Create a torus
manage_probuilder(action="create_shape", properties={
"shape_type": "Torus", "name": "Ring",
"innerRadius": 0.3, "outerRadius": 2.0,
"rows": 24, "columns": 32
})
# Smooth it for organic look
manage_probuilder(action="auto_smooth", target="Ring",
properties={"angleThreshold": 60})
# Assign metallic material
manage_probuilder(action="set_face_material", target="Ring",
properties={"faceIndices": [], "materialPath": "Assets/Materials/Gold.mat"})
# Note: empty faceIndices = all faces
```
## Batch Patterns
Use `batch_execute` for multi-step workflows to reduce round-trips:
```python
batch_execute(commands=[
{"tool": "manage_probuilder", "params": {
"action": "create_shape",
"properties": {"shape_type": "Cube", "name": "Column1", "position": [0, 0, 0]}
}},
{"tool": "manage_probuilder", "params": {
"action": "create_shape",
"properties": {"shape_type": "Cube", "name": "Column2", "position": [5, 0, 0]}
}},
{"tool": "manage_probuilder", "params": {
"action": "create_shape",
"properties": {"shape_type": "Cube", "name": "Column3", "position": [10, 0, 0]}
}},
])
```
## Known Limitations
### Not Yet Working
These actions exist in the API but have known bugs that prevent them from working correctly:
| Action | Issue | Workaround |
|--------|-------|------------|
| `set_pivot` | Vertex positions don't persist through `ToMesh()`/`RefreshMesh()`. The `positions` property setter is overwritten when ProBuilder rebuilds the mesh. Needs `SetVertices(IList<Vertex>)` or direct `m_Positions` field access. | Use `center_pivot` instead, or position objects via Transform. |
| `convert_to_probuilder` | `MeshImporter` constructor throws internally. May need ProBuilder's editor-only `ProBuilderize` API instead of runtime `MeshImporter`. | Create shapes natively with `create_shape` or `create_poly_shape` instead of converting existing meshes. |
### General Limitations
- Face indices are **not stable** across edits -- always re-query `get_mesh_info` after any modification
- Edge data is capped at **200 edges** in `get_mesh_info` results
- Face data is capped at **100 faces** in `get_mesh_info` results
- `subdivide` uses `ConnectElements.Connect` internally (ProBuilder has no public `Subdivide` API), which connects face midpoints rather than traditional quad subdivision
## Key Rules
1. **Always get_mesh_info before editing** -- face indices are not stable across edits
2. **Re-query after modifications** -- subdivide, extrude, delete all change face indices
3. **Use direction labels** -- don't guess face indices, use the direction field
4. **Cleanup after editing** -- center_pivot + validate is good practice
5. **Auto-smooth for organic shapes** -- 30 degrees is a good default
6. **Prefer ProBuilder over primitives** -- when the package is available and you need editable geometry
7. **Use batch_execute** -- for creating multiple shapes or repetitive operations
8. **Screenshot to verify** -- use `manage_camera(action="screenshot", include_image=True)` to check visual results after complex edits
@@ -0,0 +1,645 @@
# Unity-MCP Resources Reference
Resources provide read-only access to Unity state. Use resources to inspect before using tools to modify.
## Table of Contents
- [Editor State Resources](#editor-state-resources)
- [Camera Resources](#camera-resources)
- [Graphics Resources](#graphics-resources)
- [Scene & GameObject Resources](#scene--gameobject-resources)
- [Prefab Resources](#prefab-resources)
- [Project Resources](#project-resources)
- [Instance Resources](#instance-resources)
- [Test Resources](#test-resources)
---
## URI Scheme
All resources use `mcpforunity://` scheme:
```
mcpforunity://{category}/{resource_path}[?query_params]
```
**Categories:** `editor`, `scene`, `prefab`, `project`, `pipeline`, `rendering`, `menu-items`, `custom-tools`, `tests`, `instances`
---
## Editor State Resources
### mcpforunity://editor/state
**Purpose:** Editor readiness snapshot - check before tool operations.
**Returns:**
```json
{
"unity_version": "2022.3.10f1",
"is_compiling": false,
"is_domain_reload_pending": false,
"play_mode": {
"is_playing": false,
"is_paused": false
},
"active_scene": {
"path": "Assets/Scenes/Main.unity",
"name": "Main"
},
"ready_for_tools": true,
"blocking_reasons": [],
"recommended_retry_after_ms": null,
"staleness": {
"age_ms": 150,
"is_stale": false
}
}
```
**Key Fields:**
- `ready_for_tools`: Only proceed if `true`
- `is_compiling`: Wait if `true`
- `blocking_reasons`: Array explaining why tools might fail
- `recommended_retry_after_ms`: Suggested wait time
### mcpforunity://editor/selection
**Purpose:** Currently selected objects.
**Returns:**
```json
{
"activeObject": "Player",
"activeGameObject": "Player",
"activeInstanceID": 12345,
"count": 3,
"gameObjects": ["Player", "Enemy", "Wall"],
"assetGUIDs": []
}
```
### mcpforunity://editor/active-tool
**Purpose:** Current editor tool state.
**Returns:**
```json
{
"activeTool": "Move",
"isCustom": false,
"pivotMode": "Center",
"pivotRotation": "Global"
}
```
### mcpforunity://editor/windows
**Purpose:** All open editor windows.
**Returns:**
```json
{
"windows": [
{
"title": "Scene",
"typeName": "UnityEditor.SceneView",
"isFocused": true,
"position": {"x": 0, "y": 0, "width": 800, "height": 600}
}
]
}
```
### mcpforunity://editor/prefab-stage
**Purpose:** Current prefab editing context.
**Returns:**
```json
{
"isOpen": true,
"assetPath": "Assets/Prefabs/Player.prefab",
"prefabRootName": "Player",
"isDirty": false
}
```
---
## Camera Resources
### mcpforunity://scene/cameras
**Purpose:** List all cameras in the scene (Unity Camera + CinemachineCamera) with full status. Read this before using `manage_camera` to understand the current camera setup.
**Returns:**
```json
{
"brain": {
"exists": true,
"gameObject": "Main Camera",
"instanceID": 55504,
"activeCameraName": "Cam_Cinematic",
"activeCameraID": -39420,
"isBlending": false
},
"cinemachineCameras": [
{
"instanceID": -39420,
"name": "Cam_Cinematic",
"isLive": true,
"priority": 50,
"follow": {"name": "CameraTarget", "instanceID": -26766},
"lookAt": {"name": "CameraTarget", "instanceID": -26766},
"body": "CinemachineThirdPersonFollow",
"aim": "CinemachineRotationComposer",
"noise": "CinemachineBasicMultiChannelPerlin",
"extensions": []
}
],
"unityCameras": [
{
"instanceID": 55504,
"name": "Main Camera",
"depth": 0.0,
"fieldOfView": 50.0,
"hasBrain": true
}
],
"cinemachineInstalled": true
}
```
**Key Fields:**
- `brain`: CinemachineBrain status — which camera is active, blend state
- `cinemachineCameras`: All CinemachineCamera components with pipeline info (body, aim, noise, extensions)
- `unityCameras`: All Unity Camera components with depth and FOV
- `cinemachineInstalled`: Whether Cinemachine package is available
**Use with:** `manage_camera` tool for creating/configuring cameras
---
## Graphics Resources
### mcpforunity://scene/volumes
**Purpose:** List all Volume components in the scene with effects and parameters. Read this before using `manage_graphics` volume actions.
**Returns:**
```json
{
"pipeline": "Universal (URP)",
"volumes": [
{
"name": "PostProcessVolume",
"instance_id": -24600,
"is_global": true,
"weight": 1.0,
"priority": 0,
"blend_distance": 0,
"profile": "MyProfile",
"profile_path": "Assets/Settings/MyProfile.asset",
"effects": [
{
"type": "Bloom",
"active": true,
"overridden_params": ["intensity", "threshold", "scatter"]
},
{
"type": "Vignette",
"active": true,
"overridden_params": ["intensity", "smoothness"]
}
]
}
]
}
```
**Key Fields:**
- `is_global`: Whether the volume applies everywhere or only within its collider bounds
- `effects[].overridden_params`: Which parameters are actively overridden (not using defaults)
- `profile_path`: Empty string for embedded profiles, asset path for shared profiles
**Use with:** `manage_graphics` volume actions (volume_create, volume_add_effect, volume_set_effect, etc.)
### mcpforunity://rendering/stats
**Purpose:** Current rendering performance counters (draw calls, batches, triangles, memory).
**Returns:**
```json
{
"draw_calls": 42,
"batches": 35,
"set_pass_calls": 12,
"triangles": 15234,
"vertices": 8456,
"dynamic_batches": 5,
"static_batches": 20,
"shadow_casters": 3,
"render_textures": 8,
"render_textures_bytes": 16777216,
"visible_skinned_meshes": 2
}
```
**Use with:** `manage_graphics` stats actions (stats_get, stats_list_counters, stats_get_memory)
### mcpforunity://pipeline/renderer-features
**Purpose:** URP renderer features on the active renderer (SSAO, Decals, etc.).
**Returns:**
```json
{
"rendererDataName": "PC_Renderer",
"features": [
{
"index": 0,
"name": "ScreenSpaceAmbientOcclusion",
"type": "ScreenSpaceAmbientOcclusion",
"isActive": true,
"properties": { "m_Settings": "Generic" }
}
]
}
```
**Key Fields:**
- `index`: Position in the feature list (use for feature_toggle, feature_remove, feature_configure)
- `isActive`: Whether the feature is enabled
- `rendererDataName`: Which URP renderer data asset is active
**Use with:** `manage_graphics` feature actions (feature_list, feature_add, feature_remove, feature_toggle, etc.)
---
## Scene & GameObject Resources
### mcpforunity://scene/gameobject-api
**Purpose:** Documentation for GameObject resources (read this first).
### mcpforunity://scene/gameobject/{instance_id}
**Purpose:** Basic GameObject data (metadata, no component properties).
**Parameters:**
- `instance_id` (int): GameObject instance ID from `find_gameobjects`
**Returns:**
```json
{
"instanceID": 12345,
"name": "Player",
"tag": "Player",
"layer": 8,
"layerName": "Player",
"active": true,
"activeInHierarchy": true,
"isStatic": false,
"transform": {
"position": [0, 1, 0],
"rotation": [0, 0, 0],
"scale": [1, 1, 1]
},
"parent": {"instanceID": 0},
"children": [{"instanceID": 67890}],
"componentTypes": ["Transform", "Rigidbody", "PlayerController"],
"path": "/Player"
}
```
### mcpforunity://scene/gameobject/{instance_id}/components
**Purpose:** All components with full property serialization (paginated).
**Parameters:**
- `instance_id` (int): GameObject instance ID
- `page_size` (int): Default 25, max 100
- `cursor` (int): Pagination cursor
- `include_properties` (bool): Default true, set false for just types
**Returns:**
```json
{
"gameObjectID": 12345,
"gameObjectName": "Player",
"components": [
{
"type": "Transform",
"properties": {
"position": {"x": 0, "y": 1, "z": 0},
"rotation": {"x": 0, "y": 0, "z": 0, "w": 1}
}
},
{
"type": "Rigidbody",
"properties": {
"mass": 1.0,
"useGravity": true
}
}
],
"cursor": 0,
"pageSize": 25,
"nextCursor": null,
"hasMore": false
}
```
### mcpforunity://scene/gameobject/{instance_id}/component/{component_name}
**Purpose:** Single component with full properties.
**Parameters:**
- `instance_id` (int): GameObject instance ID
- `component_name` (string): e.g., "Rigidbody", "Camera", "Transform"
**Returns:**
```json
{
"gameObjectID": 12345,
"gameObjectName": "Player",
"component": {
"type": "Rigidbody",
"properties": {
"mass": 1.0,
"drag": 0,
"angularDrag": 0.05,
"useGravity": true,
"isKinematic": false
}
}
}
```
---
## Prefab Resources
### mcpforunity://prefab-api
**Purpose:** Documentation for prefab resources.
### mcpforunity://prefab/{encoded_path}
**Purpose:** Prefab asset information.
**Parameters:**
- `encoded_path` (string): URL-encoded path, e.g., `Assets%2FPrefabs%2FPlayer.prefab`
**Path Encoding:**
```
Assets/Prefabs/Player.prefab → Assets%2FPrefabs%2FPlayer.prefab
```
**Returns:**
```json
{
"assetPath": "Assets/Prefabs/Player.prefab",
"guid": "abc123...",
"prefabType": "Regular",
"rootObjectName": "Player",
"rootComponentTypes": ["Transform", "PlayerController"],
"childCount": 5,
"isVariant": false,
"parentPrefab": null
}
```
### mcpforunity://prefab/{encoded_path}/hierarchy
**Purpose:** Full prefab hierarchy with nested prefab info.
**Returns:**
```json
{
"prefabPath": "Assets/Prefabs/Player.prefab",
"total": 6,
"items": [
{
"name": "Player",
"instanceId": 12345,
"path": "/Player",
"activeSelf": true,
"childCount": 2,
"componentTypes": ["Transform", "PlayerController"]
},
{
"name": "Model",
"path": "/Player/Model",
"isNestedPrefab": true,
"nestedPrefabPath": "Assets/Prefabs/PlayerModel.prefab"
}
]
}
```
---
## Project Resources
### mcpforunity://project/info
**Purpose:** Static project configuration.
**Returns:**
```json
{
"projectRoot": "/Users/dev/MyProject",
"projectName": "MyProject",
"unityVersion": "2022.3.10f1",
"platform": "StandaloneWindows64",
"assetsPath": "/Users/dev/MyProject/Assets"
}
```
### mcpforunity://project/tags
**Purpose:** All tags defined in TagManager.
**Returns:**
```json
["Untagged", "Respawn", "Finish", "EditorOnly", "MainCamera", "Player", "GameController", "Enemy"]
```
### mcpforunity://project/layers
**Purpose:** All layers with indices (0-31).
**Returns:**
```json
{
"0": "Default",
"1": "TransparentFX",
"2": "Ignore Raycast",
"4": "Water",
"5": "UI",
"8": "Player",
"9": "Enemy"
}
```
### mcpforunity://menu-items
**Purpose:** All available Unity menu items.
**Returns:**
```json
[
"File/New Scene",
"File/Open Scene",
"File/Save",
"Edit/Undo",
"Edit/Redo",
"GameObject/Create Empty",
"GameObject/3D Object/Cube",
"Window/General/Console"
]
```
### mcpforunity://custom-tools
**Purpose:** Custom tools available in the active Unity project.
**Returns:**
```json
{
"project_id": "MyProject",
"tool_count": 3,
"tools": [
{
"name": "capture_screenshot",
"description": "Capture screenshots in Unity",
"parameters": [
{"name": "filename", "type": "string", "required": true},
{"name": "width", "type": "int", "required": false},
{"name": "height", "type": "int", "required": false}
]
}
]
}
```
---
## Instance Resources
### mcpforunity://instances
**Purpose:** All running Unity Editor instances (for multi-instance workflows).
**Returns:**
```json
{
"transport": "http",
"instance_count": 2,
"instances": [
{
"id": "MyProject@abc123",
"name": "MyProject",
"hash": "abc123",
"unity_version": "2022.3.10f1",
"connected_at": "2024-01-15T10:30:00Z"
},
{
"id": "TestProject@def456",
"name": "TestProject",
"hash": "def456",
"unity_version": "2022.3.10f1",
"connected_at": "2024-01-15T11:00:00Z"
}
],
"warnings": []
}
```
**Use with:** `set_active_instance(instance="MyProject@abc123")`
---
## Test Resources
### mcpforunity://tests
**Purpose:** All tests in the project.
**Returns:**
```json
[
{
"name": "TestSomething",
"full_name": "MyTests.TestSomething",
"mode": "EditMode"
},
{
"name": "TestOther",
"full_name": "MyTests.TestOther",
"mode": "PlayMode"
}
]
```
### mcpforunity://tests/{mode}
**Purpose:** Tests filtered by mode.
**Parameters:**
- `mode` (string): "EditMode" or "PlayMode"
**Example:** `mcpforunity://tests/EditMode`
---
## Best Practices
### 1. Check Editor State First
```python
# Before any complex operation:
# Read mcpforunity://editor/state
# Check ready_for_tools == true
```
### 2. Use Find Then Read Pattern
```python
# 1. find_gameobjects to get IDs
result = find_gameobjects(search_term="Player")
# 2. Read resource for full data
# mcpforunity://scene/gameobject/{id}
```
### 3. Paginate Large Queries
```python
# Start with include_properties=false for component lists
# mcpforunity://scene/gameobject/{id}/components?include_properties=false&page_size=25
# Then read specific components as needed
# mcpforunity://scene/gameobject/{id}/component/Rigidbody
```
### 4. URL-Encode Prefab Paths
```python
# Wrong:
# mcpforunity://prefab/Assets/Prefabs/Player.prefab
# Correct:
# mcpforunity://prefab/Assets%2FPrefabs%2FPlayer.prefab
```
### 5. Multi-Instance Awareness
```python
# Always check mcpforunity://instances when:
# - First connecting
# - Commands fail unexpectedly
# - Working with multiple projects
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff