Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/unity-mcp-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ uri="file:///full/path/to/file.cs"
| **Editor** | `manage_editor`, `execute_menu_item`, `read_console` | Editor control, package deployment (`deploy_package`/`restore_package`), undo/redo (`undo`/`redo` 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). |
| **Camera** | `manage_camera` | Camera management (Unity Camera + Cinemachine). **Tier 1** (always available): create, target, lens, priority, list, screenshot. **Tier 2** (requires the Cinemachine 3 camera API): 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 the installed package version and native API support. Preserve Cinemachine 2 projects; use `execute_code` with the installed API. See [tools-reference.md](references/tools-reference.md#camera-tools). |
| **Animation** | `manage_animation`, `manage_sprite` | Animator control, clips and controllers. **2D sprite sheets**: `manage_sprite(action="get_info")` returns a PNG or JPEG sheet as an image to count the grid from, then `full_setup` slices it and builds clips and a controller; clip names decide the states (idle, walk/run, attack-type triggers). Off by default over HTTP: `manage_tools(action="activate", group="animation")`. |
| **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). |
Expand Down
4 changes: 3 additions & 1 deletion .claude/skills/unity-mcp-skill/references/tools-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,9 @@ Discover available custom tools via `mcpforunity://custom-tools` resource.

### manage_camera

Unified camera management (Unity Camera + Cinemachine). Works without Cinemachine using basic Camera; unlocks presets, pipelines, and blending when Cinemachine is installed. Use `ping` to check availability.
Unified camera management (Unity Camera + Cinemachine). Basic Camera operations are always available; presets, pipelines, and blending use the Cinemachine 3 camera API. `ping` returns `installed`, `version` (UPM release when registered), `cinemachine` (native API available), and `supportedApiMajor` (3).

Before writing package-specific code, use `manage_packages(action="get_package_info", package="com.unity.cinemachine")`. Preserve an existing Cinemachine 2 version and use `execute_code` with its installed API; unsupported native actions explain this limitation without prompting an upgrade. The Dependencies tab also supports exact package versions and preserves unchanged installations in Install All.

**Parameters:**

Expand Down
63 changes: 63 additions & 0 deletions MCPForUnity/Editor/Dependencies/PackageVersionSelection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace MCPForUnity.Editor.Dependencies
{
/// <summary>Builds exact optional-package requests while preserving installed defaults.</summary>
internal sealed class PackageVersionSelection
{
private static readonly Regex ExactVersion = new Regex(
@"\A(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?\z",
RegexOptions.CultureInvariant);

internal string PackageId { get; }
internal string InstalledVersion { get; }
internal bool IsInstalled { get; }
internal string Version { get; set; }
internal string SessionKey => "MCPForUnity.OptionalPackageVersion." + PackageId;

internal PackageVersionSelection(string packageId, string installedVersion, bool isInstalled)
{
PackageId = packageId;
InstalledVersion = installedVersion;
IsInstalled = isInstalled;
Version = installedVersion ?? string.Empty;
}

internal bool TryGetRequest(out string request, out string error)
{
request = null;
error = null;
string version = Version?.Trim() ?? string.Empty;
// No request means even Git/local packages keep their original source.
if (IsInstalled && (InstalledVersion == null || version.Length == 0 || version == InstalledVersion)) return true;
if (version.Length > 0 && !ExactVersion.IsMatch(version))
{
error = "Use an exact package version, such as 2.4.0 or 3.0.0-pre.1, or leave it empty.";
return false;
}
request = version.Length == 0 ? PackageId : PackageId + "@" + version;
return true;
}

internal static bool TryCollectRequests(IEnumerable<PackageVersionSelection> selections,
out string[] requests, out string error)
{
var result = new List<string>();
foreach (var selection in selections)
{
if (!selection.TryGetRequest(out string request, out error))
{
requests = Array.Empty<string>();
error = selection.PackageId + ": " + error;
return false;
}
if (request != null) result.Add(request);
}
requests = result.ToArray();
error = null;
return true;
}
}
}
11 changes: 11 additions & 0 deletions MCPForUnity/Editor/Dependencies/PackageVersionSelection.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions MCPForUnity/Editor/Tools/Cameras/CameraCreate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ internal static object CreateBasicCamera(JObject @params)
return new
{
success = true,
message = $"Created basic Camera '{name}' (Cinemachine not installed — using Unity Camera).",
message = $"Created basic Camera '{name}'. " + CameraHelpers.GetUnavailableCinemachineMessage(),
data = new
{
instanceID = go.GetInstanceIDCompat(),
cinemachine = false,
hint = "Install com.unity.cinemachine for presets, blending, and virtual camera features."
hint = CameraHelpers.IsCinemachineInstalled
? CameraHelpers.GetFallbackSuggestion("create_camera")
: "Install com.unity.cinemachine for presets, blending, and virtual camera features."
}
};
}
Expand Down
33 changes: 21 additions & 12 deletions MCPForUnity/Editor/Tools/Cameras/CameraHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,26 @@ private static void DetectCinemachine()

internal static string GetCinemachineVersion()
{
if (!HasCinemachine || _cmCameraType == null)
return null;
// Assembly versions need not match the installed UPM release.
var package = UnityEditor.PackageManager.PackageInfo.GetAllRegisteredPackages()
.FirstOrDefault(info => info.name == "com.unity.cinemachine");
if (package != null) return package.version;

var cameraType = CinemachineCameraType
?? UnityTypeResolver.ResolveComponent("Cinemachine.CinemachineVirtualCamera");
if (cameraType == null) return null;
return cameraType.Assembly.GetName().Version?.ToString() ?? "unknown";
}

try
{
var assembly = _cmCameraType.Assembly;
var version = assembly.GetName().Version;
return version?.ToString();
}
catch
{
return "unknown";
}
internal static bool IsCinemachineInstalled => HasCinemachine || GetCinemachineVersion() != null;

internal static string GetUnavailableCinemachineMessage()
{
string version = GetCinemachineVersion();
return version == null
? "Cinemachine not installed."
: $"Cinemachine {version} is installed, but manage_camera requires the Cinemachine 3 camera API. "
+ "Keep the project's installed version and use execute_code with that version's API.";
}

internal static GameObject FindTargetGameObject(JObject @params)
Expand Down Expand Up @@ -245,6 +252,8 @@ internal static Component GetPipelineComponent(Component cmCamera, string stageN

internal static string GetFallbackSuggestion(string action)
{
if (IsCinemachineInstalled && !HasCinemachine)
return "Use manage_packages get_package_info to confirm the installed version before writing Cinemachine code.";
return action switch
{
"set_body" or "set_aim" => "Use 'set_lens' and 'set_target' for basic camera configuration.",
Expand Down
8 changes: 5 additions & 3 deletions MCPForUnity/Editor/Tools/Cameras/ManageCamera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public static object HandleCommand(JObject @params)
success = true,
message = CameraHelpers.HasCinemachine
? "Cinemachine is available."
: "Cinemachine not installed. Basic Camera operations available.",
: CameraHelpers.GetUnavailableCinemachineMessage() + " Basic Camera operations available.",
data = new
{
cinemachine = CameraHelpers.HasCinemachine,
version = CameraHelpers.GetCinemachineVersion()
installed = CameraHelpers.IsCinemachineInstalled,
version = CameraHelpers.GetCinemachineVersion(),
supportedApiMajor = 3
}
};

Expand Down Expand Up @@ -79,7 +81,7 @@ public static object HandleCommand(JObject @params)
if (!CameraHelpers.HasCinemachine)
{
return new ErrorResponse(
$"Action '{action}' requires the Cinemachine package (com.unity.cinemachine). "
$"Action '{action}' is unavailable. " + CameraHelpers.GetUnavailableCinemachineMessage() + " "
+ CameraHelpers.GetFallbackSuggestion(action));
}

Expand Down
Loading
Loading