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)**
+
+
+**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(