From 55f7c55389a3fd7afe773ffa521687c0e85cc7ca Mon Sep 17 00:00:00 2001 From: Scriptwonder <1300285021@qq.com> Date: Mon, 14 Jul 2025 01:42:16 -0400 Subject: [PATCH] Update for ManageShader Bug fix and error handling check for the PR. Great work and I love what I built! --- README.md | 5 +- .../Editor/Tools/CommandRegistry.cs | 1 + UnityMcpBridge/Editor/Tools/ManageShader.cs | 107 ++++++++++-------- .../Editor/Tools/ManageShader.cs.meta | 11 ++ UnityMcpBridge/Editor/UnityMcpBridge.cs | 1 + 5 files changed, 79 insertions(+), 46 deletions(-) create mode 100644 UnityMcpBridge/Editor/Tools/ManageShader.cs.meta diff --git a/README.md b/README.md index e422540..d4035a9 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Unity MCP acts as a bridge, allowing AI assistants (like Claude, Cursor) to inte * `manage_editor`: Controls and queries the editor's state and settings. * `manage_scene`: Manages scenes (load, save, create, get hierarchy, etc.). * `manage_asset`: Performs asset operations (import, create, modify, delete, etc.). + * `manage_shader`: Performs shader CRUD operations (create, read, modify, delete). * `manage_gameobject`: Manages GameObjects: create, modify, delete, find, and component operations. * `execute_menu_item`: Executes a menu item via its path (e.g., "File/Save Project"). @@ -81,7 +82,9 @@ Unity MCP connects your tools using two components: Connect your MCP Client (Claude, Cursor, etc.) to the Python server you installed in Step 1. -**Option A: Auto-Configure (Recommended for Claude/Cursor)** +image + +**Option A: Auto-Configure (Recommended for Claude/Cursor/VSC Copilot)** 1. In Unity, go to `Window > Unity MCP`. 2. Click `Auto Configure Claude` or `Auto Configure Cursor`. diff --git a/UnityMcpBridge/Editor/Tools/CommandRegistry.cs b/UnityMcpBridge/Editor/Tools/CommandRegistry.cs index 18e2de9..ce502b4 100644 --- a/UnityMcpBridge/Editor/Tools/CommandRegistry.cs +++ b/UnityMcpBridge/Editor/Tools/CommandRegistry.cs @@ -20,6 +20,7 @@ namespace UnityMcpBridge.Editor.Tools { "HandleManageAsset", ManageAsset.HandleCommand }, { "HandleReadConsole", ReadConsole.HandleCommand }, { "HandleExecuteMenuItem", ExecuteMenuItem.HandleCommand }, + { "HandleManageShader", ManageShader.HandleCommand}, }; /// diff --git a/UnityMcpBridge/Editor/Tools/ManageShader.cs b/UnityMcpBridge/Editor/Tools/ManageShader.cs index 49bbf15..03b28f1 100644 --- a/UnityMcpBridge/Editor/Tools/ManageShader.cs +++ b/UnityMcpBridge/Editor/Tools/ManageShader.cs @@ -89,7 +89,12 @@ namespace UnityMcpBridge.Editor.Tools { try { - Directory.CreateDirectory(fullPathDir); + if (!Directory.Exists(fullPathDir)) + { + Directory.CreateDirectory(fullPathDir); + // Refresh AssetDatabase to recognize new folders + AssetDatabase.Refresh(); + } } catch (Exception e) { @@ -150,6 +155,14 @@ namespace UnityMcpBridge.Editor.Tools ); } + // Add validation for shader name conflicts in Unity + if (Shader.Find(name) != null) + { + return Response.Error( + $"A shader with name '{name}' already exists in the project. Choose a different name." + ); + } + // Generate default content if none provided if (string.IsNullOrEmpty(contents)) { @@ -184,6 +197,7 @@ namespace UnityMcpBridge.Editor.Tools string contents = File.ReadAllText(fullPath); // Return both normal and encoded contents for larger files + //TODO: Consider a threshold for large files bool isLarge = contents.Length > 10000; // If content is large, include encoded version var responseData = new { @@ -227,6 +241,7 @@ namespace UnityMcpBridge.Editor.Tools { File.WriteAllText(fullPath, contents); AssetDatabase.ImportAsset(relativePath); + AssetDatabase.Refresh(); return Response.Success( $"Shader '{Path.GetFileName(relativePath)}' updated successfully.", new { path = relativePath } @@ -268,58 +283,60 @@ namespace UnityMcpBridge.Editor.Tools } } + //This is a CGProgram template + //TODO: making a HLSL template as well? private static string GenerateDefaultShaderContent(string name) { return @"Shader """ + name + @""" -{ - Properties - { - _MainTex (""Texture"", 2D) = ""white"" {} - } - SubShader - { - Tags { ""RenderType""=""Opaque"" } - LOD 100 - - Pass { - CGPROGRAM - #pragma vertex vert - #pragma fragment frag - #include ""UnityCG.cginc"" - - struct appdata + Properties { - float4 vertex : POSITION; - float2 uv : TEXCOORD0; - }; - - struct v2f - { - float2 uv : TEXCOORD0; - float4 vertex : SV_POSITION; - }; - - sampler2D _MainTex; - float4 _MainTex_ST; - - v2f vert (appdata v) - { - v2f o; - o.vertex = UnityObjectToClipPos(v.vertex); - o.uv = TRANSFORM_TEX(v.uv, _MainTex); - return o; + _MainTex (""Texture"", 2D) = ""white"" {} } - - fixed4 frag (v2f i) : SV_Target + SubShader { - fixed4 col = tex2D(_MainTex, i.uv); - return col; + Tags { ""RenderType""=""Opaque"" } + LOD 100 + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include ""UnityCG.cginc"" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + fixed4 col = tex2D(_MainTex, i.uv); + return col; + } + ENDCG + } } - ENDCG - } - } -}"; + }"; } } } \ No newline at end of file diff --git a/UnityMcpBridge/Editor/Tools/ManageShader.cs.meta b/UnityMcpBridge/Editor/Tools/ManageShader.cs.meta new file mode 100644 index 0000000..89d10cd --- /dev/null +++ b/UnityMcpBridge/Editor/Tools/ManageShader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bcf4f1f3110494344b2af9324cf5c571 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityMcpBridge/Editor/UnityMcpBridge.cs b/UnityMcpBridge/Editor/UnityMcpBridge.cs index 9276c05..e6b46db 100644 --- a/UnityMcpBridge/Editor/UnityMcpBridge.cs +++ b/UnityMcpBridge/Editor/UnityMcpBridge.cs @@ -378,6 +378,7 @@ namespace UnityMcpBridge.Editor "manage_editor" => ManageEditor.HandleCommand(paramsObject), "manage_gameobject" => ManageGameObject.HandleCommand(paramsObject), "manage_asset" => ManageAsset.HandleCommand(paramsObject), + "manage_shader" => ManageShader.HandleCommand(paramsObject), "read_console" => ReadConsole.HandleCommand(paramsObject), "execute_menu_item" => ExecuteMenuItem.HandleCommand(paramsObject), _ => throw new ArgumentException(