Skip to content

Commit 25357a0

Browse files
committed
fix(profiler): address code review — error on unknown category, tighten reflection
1 parent 1f0fb1d commit 25357a0

8 files changed

Lines changed: 320 additions & 52 deletions

File tree

.claude/skills/unity-mcp-skill/references/tools-reference.md

Lines changed: 204 additions & 39 deletions
Large diffs are not rendered by default.

MCPForUnity/Editor/Tools/Profiler/Operations/CounterOps.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ internal static async Task<object> GetCountersAsync(JObject @params)
2020
return new ErrorResponse(categoryResult.ErrorMessage);
2121

2222
string categoryName = categoryResult.Value;
23-
ProfilerCategory category = ResolveCategory(categoryName);
23+
var resolved = ResolveCategory(categoryName, out string categoryError);
24+
if (resolved == null)
25+
return new ErrorResponse(categoryError);
26+
ProfilerCategory category = resolved.Value;
2427

2528
// Get counter names: explicit list or discover all in category
2629
var counterNames = GetRequestedCounters(p, category);
@@ -91,8 +94,16 @@ void Tick()
9194
return tcs.Task;
9295
}
9396

94-
private static ProfilerCategory ResolveCategory(string name)
97+
private static readonly string[] ValidCategories = new[]
9598
{
99+
"Render", "Scripts", "Memory", "Physics", "Physics2D", "Animation",
100+
"Audio", "Lighting", "Network", "Gui", "UI", "Ai", "Video",
101+
"Loading", "Input", "Vr", "Internal", "Particles", "FileIO", "VirtualTexturing"
102+
};
103+
104+
internal static ProfilerCategory? ResolveCategory(string name, out string error)
105+
{
106+
error = null;
96107
switch (name.ToLowerInvariant())
97108
{
98109
case "render": return ProfilerCategory.Render;
@@ -114,7 +125,9 @@ private static ProfilerCategory ResolveCategory(string name)
114125
case "particles": return ProfilerCategory.Particles;
115126
case "fileio": return ProfilerCategory.FileIO;
116127
case "virtualtexturing": return ProfilerCategory.VirtualTexturing;
117-
default: return ProfilerCategory.Render;
128+
default:
129+
error = $"Unknown category '{name}'. Valid: {string.Join(", ", ValidCategories)}";
130+
return null;
118131
}
119132
}
120133
}

MCPForUnity/Editor/Tools/Profiler/Operations/FrameDebuggerOps.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ internal static class FrameDebuggerOps
1111
private static readonly Type UtilType;
1212
private static readonly PropertyInfo EventCountProp;
1313
private static readonly MethodInfo EnableMethod;
14-
private static readonly MethodInfo DisableMethod;
1514
private static readonly MethodInfo GetEventDataMethod;
1615
private static readonly bool ReflectionAvailable;
1716

@@ -24,9 +23,12 @@ static FrameDebuggerOps()
2423
{
2524
EventCountProp = UtilType.GetProperty("eventsCount", BindingFlags.Public | BindingFlags.Static)
2625
?? UtilType.GetProperty("count", BindingFlags.Public | BindingFlags.Static);
27-
EnableMethod = UtilType.GetMethod("SetEnabled", BindingFlags.Public | BindingFlags.Static);
28-
DisableMethod = EnableMethod; // Same method, different arg
29-
GetEventDataMethod = UtilType.GetMethod("GetFrameEventData", BindingFlags.Public | BindingFlags.Static);
26+
EnableMethod = UtilType.GetMethod("SetEnabled", BindingFlags.Public | BindingFlags.Static,
27+
null, new[] { typeof(bool), typeof(int) }, null)
28+
?? UtilType.GetMethod("SetEnabled", BindingFlags.Public | BindingFlags.Static);
29+
GetEventDataMethod = UtilType.GetMethod("GetFrameEventData", BindingFlags.Public | BindingFlags.Static,
30+
null, new[] { typeof(int) }, null)
31+
?? UtilType.GetMethod("GetFrameEventData", BindingFlags.Public | BindingFlags.Static);
3032
}
3133
ReflectionAvailable = UtilType != null && EventCountProp != null;
3234
}

MCPForUnity/Editor/Tools/Profiler/Operations/MemorySnapshotOps.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ internal static async Task<object> TakeSnapshotAsync(JObject @params)
3838
new[] { typeof(string), typeof(Action<string, bool>), typeof(Action<string, bool, UnityEditor.DebugScreenCapture>), typeof(uint) });
3939

4040
if (takeMethod == null)
41-
takeMethod = MemoryProfilerType.GetMethod("TakeSnapshot");
41+
{
42+
// Try 2-param overload: TakeSnapshot(string, Action<string, bool>)
43+
takeMethod = MemoryProfilerType.GetMethod("TakeSnapshot",
44+
new[] { typeof(string), typeof(Action<string, bool>) });
45+
}
4246

4347
if (takeMethod == null)
4448
return new ErrorResponse("Could not find TakeSnapshot method on MemoryProfiler. API may have changed.");
@@ -61,7 +65,13 @@ internal static async Task<object> TakeSnapshotAsync(JObject @params)
6165
}
6266
};
6367

64-
takeMethod.Invoke(null, new object[] { snapshotPath, callback, null, 0u });
68+
int paramCount = takeMethod.GetParameters().Length;
69+
if (paramCount == 4)
70+
takeMethod.Invoke(null, new object[] { snapshotPath, callback, null, 0u });
71+
else if (paramCount == 2)
72+
takeMethod.Invoke(null, new object[] { snapshotPath, callback });
73+
else
74+
return new ErrorResponse($"TakeSnapshot has unexpected {paramCount} parameters. API may have changed.");
6575
}
6676
catch (Exception ex)
6777
{

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
<details>
2121
<summary><strong>Recent Updates</strong></summary>
2222

23-
* **v9.6.2 (beta)** — New `manage_physics` tool (21 actions): physics settings, layer collision matrix, physics materials, joints (5 3D + 9 2D types), queries (raycast, raycast_all, linecast, shapecast, overlap), force application (AddForce/AddTorque/AddExplosionForce), rigidbody configuration, scene-wide validation, and edit-mode simulation. Full 3D and 2D support.
23+
* **v9.6.3 (beta)** — New `manage_profiler` tool (14 actions): Profiler session control (start/stop/status/set areas), frame timing and counter reads, object memory queries, memory snapshots (take/list/compare via com.unity.memoryprofiler), and Frame Debugger (enable/disable/get events). Group: `profiling`.
24+
* **v9.6.2** — New `manage_physics` tool (21 actions): physics settings, layer collision matrix, physics materials, joints (5 3D + 9 2D types), queries (raycast, raycast_all, linecast, shapecast, overlap), force application (AddForce/AddTorque/AddExplosionForce), rigidbody configuration, scene-wide validation, and edit-mode simulation. Full 3D and 2D support.
2425
* **v9.6.1** — QoL extensions: `manage_editor` gains undo/redo actions. `manage_scene` gains multi-scene editing (additive load, close, set active, move GO between scenes), scene templates (3d_basic, 2d_basic, etc.), and scene validation with auto-repair. New `manage_build` tool: trigger player builds, switch platforms, configure player settings, manage build scenes and profiles (Unity 6+), run batch builds across multiple platforms, and async job tracking with polling. New `MaxPollSeconds` infrastructure for long-running tool operations.
2526
* **v9.5.4** — New `unity_reflect` and `unity_docs` tools for API verification: inspect live C# APIs via reflection and fetch official Unity documentation (ScriptReference, Manual, package docs). New `manage_packages` tool: install, remove, search, and manage Unity packages and scoped registries. Includes input validation, dependency checks on removal, and git URL warnings.
2627
* **v9.5.3** — New `manage_graphics` tool (33 actions): volume/post-processing, light baking, rendering stats, pipeline settings, URP renderer features. 3 new resources: `volumes`, `rendering_stats`, `renderer_features`.
@@ -96,7 +97,7 @@ openupm add com.coplaydev.unity-mcp
9697
* **Extensible** — Works with various MCP Clients
9798

9899
### Available Tools
99-
`apply_text_edits``batch_execute``create_script``debug_request_context``delete_script``execute_custom_tool``execute_menu_item``find_gameobjects``find_in_file``get_sha``get_test_job``manage_animation``manage_asset``manage_build``manage_camera``manage_components``manage_editor``manage_gameobject``manage_graphics``manage_material``manage_packages``manage_physics``manage_prefabs``manage_probuilder``manage_scene``manage_script``manage_script_capabilities``manage_scriptable_object``manage_shader``manage_texture``manage_tools``manage_ui``manage_vfx``read_console``refresh_unity``run_tests``script_apply_edits``set_active_instance``unity_docs``unity_reflect``validate_script`
100+
`apply_text_edits``batch_execute``create_script``debug_request_context``delete_script``execute_custom_tool``execute_menu_item``find_gameobjects``find_in_file``get_sha``get_test_job``manage_animation``manage_asset``manage_build``manage_camera``manage_components``manage_editor``manage_gameobject``manage_graphics``manage_material``manage_packages``manage_physics``manage_prefabs``manage_probuilder``manage_profiler``manage_scene``manage_script``manage_script_capabilities``manage_scriptable_object``manage_shader``manage_texture``manage_tools``manage_ui``manage_vfx``read_console``refresh_unity``run_tests``script_apply_edits``set_active_instance``unity_docs``unity_reflect``validate_script`
100101

101102
### Available Resources
102103
`cameras``custom_tools``renderer_features``rendering_stats``volumes``editor_active_tool``editor_prefab_stage``editor_selection``editor_state``editor_windows``gameobject``gameobject_api``gameobject_component``gameobject_components``get_tests``get_tests_for_mode``menu_items``prefab_api``prefab_hierarchy``prefab_info``project_info``project_layers``project_tags``tool_groups``unity_instances`

docs/i18n/README-zh.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
<details>
2121
<summary><strong>最近更新</strong></summary>
2222

23-
* **v9.6.2 (beta)** — 新增 `manage_physics` 工具(21个操作):物理设置、层碰撞矩阵、物理材质、关节(5种3D + 9种2D类型)、查询(raycast、raycast_all、linecast、shapecast、overlap)、力施加(AddForce/AddTorque/AddExplosionForce)、刚体配置、场景物理验证与编辑器模式模拟。全面支持3D和2D物理。
23+
* **v9.6.3 (beta)** — 新增 `manage_profiler` 工具(14个操作):Profiler 会话控制(启动/停止/状态/设置区域)、帧时间与计数器读取、对象内存查询、内存快照(通过 com.unity.memoryprofiler 进行拍摄/列表/比较)、帧调试器(启用/禁用/获取事件)。分组:`profiling`
24+
* **v9.6.2** — 新增 `manage_physics` 工具(21个操作):物理设置、层碰撞矩阵、物理材质、关节(5种3D + 9种2D类型)、查询(raycast、raycast_all、linecast、shapecast、overlap)、力施加(AddForce/AddTorque/AddExplosionForce)、刚体配置、场景物理验证与编辑器模式模拟。全面支持3D和2D物理。
2425
* **v9.6.1** — QoL 扩展:`manage_editor` 新增撤销/重做操作。`manage_scene` 新增多场景编辑(叠加加载、关闭、设置活动场景、跨场景移动物体)、场景模板(3d_basic、2d_basic 等)、场景验证与自动修复。新增 `manage_build` 工具:触发玩家构建、切换平台、配置玩家设置、管理构建场景和配置文件(Unity 6+)、跨多平台批量构建、异步任务跟踪与轮询。新增 `MaxPollSeconds` 基础设施,支持长时间运行的工具操作。
2526
* **v9.5.4** — 新增 `unity_reflect``unity_docs` 工具用于 API 验证:通过反射检查实时 C# API,获取官方 Unity 文档(ScriptReference、Manual、包文档)。新增 `manage_packages` 工具:安装、移除、搜索和管理 Unity 包及作用域注册表。包含输入验证、移除时依赖检查和 git URL 警告。
2627
* **v9.5.3** — 新增 `manage_graphics` 工具(33个操作):体积/后处理、光照烘焙、渲染统计、管线设置、URP渲染器特性。3个新资源:`volumes``rendering_stats``renderer_features`
@@ -96,7 +97,7 @@ openupm add com.coplaydev.unity-mcp
9697
* **可扩展** — 可与多种 MCP Client 配合使用
9798

9899
### 可用工具
99-
`apply_text_edits``batch_execute``create_script``debug_request_context``delete_script``execute_custom_tool``execute_menu_item``find_gameobjects``find_in_file``get_sha``get_test_job``manage_animation``manage_asset``manage_build``manage_camera``manage_components``manage_editor``manage_gameobject``manage_graphics``manage_material``manage_packages``manage_physics``manage_prefabs``manage_probuilder``manage_scene``manage_script``manage_script_capabilities``manage_scriptable_object``manage_shader``manage_texture``manage_tools``manage_ui``manage_vfx``read_console``refresh_unity``run_tests``script_apply_edits``set_active_instance``unity_docs``unity_reflect``validate_script`
100+
`apply_text_edits``batch_execute``create_script``debug_request_context``delete_script``execute_custom_tool``execute_menu_item``find_gameobjects``find_in_file``get_sha``get_test_job``manage_animation``manage_asset``manage_build``manage_camera``manage_components``manage_editor``manage_gameobject``manage_graphics``manage_material``manage_packages``manage_physics``manage_prefabs``manage_probuilder``manage_profiler``manage_scene``manage_script``manage_script_capabilities``manage_scriptable_object``manage_shader``manage_texture``manage_tools``manage_ui``manage_vfx``read_console``refresh_unity``run_tests``script_apply_edits``set_active_instance``unity_docs``unity_reflect``validate_script`
100101

101102
### 可用资源
102103
`cameras``custom_tools``renderer_features``rendering_stats``volumes``editor_active_tool``editor_prefab_stage``editor_selection``editor_state``editor_windows``gameobject``gameobject_api``gameobject_component``gameobject_components``get_tests``get_tests_for_mode``menu_items``prefab_api``prefab_hierarchy``prefab_info``project_info``project_layers``project_tags``tool_groups``unity_instances`

manifest.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@
125125
"name": "manage_probuilder",
126126
"description": "Create and edit ProBuilder meshes, shapes, and geometry operations"
127127
},
128+
{
129+
"name": "manage_profiler",
130+
"description": "Unity Profiler session control, counter reads, memory snapshots, and Frame Debugger (group: profiling)"
131+
},
128132
{
129133
"name": "manage_scene",
130134
"description": "Load, save, query hierarchy, multi-scene editing, templates, validation, and manage Unity scenes"

unity-mcp-skill/references/tools-reference.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Complete reference for all MCP tools. Each tool includes parameters, types, and
2020
- [Package Tools](#package-tools)
2121
- [Physics Tools](#physics-tools)
2222
- [ProBuilder Tools](#probuilder-tools)
23+
- [Profiler Tools](#profiler-tools)
2324
- [Docs Tools](#docs-tools)
2425

2526
---
@@ -1423,6 +1424,77 @@ See also: [ProBuilder Workflow Guide](probuilder-guide.md) for detailed patterns
14231424

14241425
---
14251426

1427+
## Profiler Tools
1428+
1429+
### `manage_profiler`
1430+
1431+
Unity Profiler session control, counter reads, memory snapshots, and Frame Debugger. Group: `profiling` (opt-in via `manage_tools`).
1432+
1433+
| Parameter | Type | Required | Description |
1434+
|-----------|------|----------|-------------|
1435+
| `action` | string | Yes | See action groups below |
1436+
| `category` | string | For get_counters | Profiler category name (e.g. `Render`, `Scripts`, `Memory`, `Physics`) |
1437+
| `counters` | list[str] | No | Specific counter names for get_counters. Omit to read all in category |
1438+
| `object_path` | string | For get_object_memory | Scene hierarchy or asset path |
1439+
| `log_file` | string | No | Path to `.raw` file for profiler_start recording |
1440+
| `enable_callstacks` | bool | No | Enable allocation callstacks for profiler_start |
1441+
| `areas` | dict[str, bool] | For profiler_set_areas | Area name to enabled/disabled mapping |
1442+
| `snapshot_path` | string | No | Output path for memory_take_snapshot |
1443+
| `search_path` | string | No | Search directory for memory_list_snapshots |
1444+
| `snapshot_a` | string | For memory_compare_snapshots | First snapshot file path |
1445+
| `snapshot_b` | string | For memory_compare_snapshots | Second snapshot file path |
1446+
| `page_size` | int | No | Page size for frame_debugger_get_events (default 50) |
1447+
| `cursor` | int | No | Cursor offset for frame_debugger_get_events |
1448+
1449+
**Action groups:**
1450+
1451+
- **Session:** `profiler_start`, `profiler_stop`, `profiler_status`, `profiler_set_areas`
1452+
- **Counters:** `get_frame_timing`, `get_counters`, `get_object_memory`
1453+
- **Memory Snapshot:** `memory_take_snapshot`, `memory_list_snapshots`, `memory_compare_snapshots` (requires `com.unity.memoryprofiler`)
1454+
- **Frame Debugger:** `frame_debugger_enable`, `frame_debugger_disable`, `frame_debugger_get_events`
1455+
- **Utility:** `ping`
1456+
1457+
```python
1458+
# Check profiler availability
1459+
manage_profiler(action="ping")
1460+
1461+
# Start profiling (optionally record to file)
1462+
manage_profiler(action="profiler_start")
1463+
manage_profiler(action="profiler_start", log_file="Assets/profiler.raw", enable_callstacks=True)
1464+
1465+
# Check profiler status
1466+
manage_profiler(action="profiler_status")
1467+
1468+
# Toggle profiler areas
1469+
manage_profiler(action="profiler_set_areas", areas={"CPU": True, "GPU": True, "Rendering": True, "Memory": False})
1470+
1471+
# Stop profiling
1472+
manage_profiler(action="profiler_stop")
1473+
1474+
# Read frame timing data (12 fields from FrameTimingManager)
1475+
manage_profiler(action="get_frame_timing")
1476+
1477+
# Read counters by category
1478+
manage_profiler(action="get_counters", category="Render")
1479+
manage_profiler(action="get_counters", category="Memory", counters=["Total Used Memory", "GC Used Memory"])
1480+
1481+
# Get memory size of a specific object
1482+
manage_profiler(action="get_object_memory", object_path="Player/Mesh")
1483+
1484+
# Memory snapshots (requires com.unity.memoryprofiler)
1485+
manage_profiler(action="memory_take_snapshot")
1486+
manage_profiler(action="memory_take_snapshot", snapshot_path="Assets/Snapshots/baseline.snap")
1487+
manage_profiler(action="memory_list_snapshots")
1488+
manage_profiler(action="memory_compare_snapshots", snapshot_a="Assets/Snapshots/before.snap", snapshot_b="Assets/Snapshots/after.snap")
1489+
1490+
# Frame Debugger
1491+
manage_profiler(action="frame_debugger_enable")
1492+
manage_profiler(action="frame_debugger_get_events", page_size=20, cursor=0)
1493+
manage_profiler(action="frame_debugger_disable")
1494+
```
1495+
1496+
---
1497+
14261498
## Docs Tools
14271499

14281500
Tools for verifying Unity C# APIs and fetching official documentation. Group: `docs`.

0 commit comments

Comments
 (0)