Skip to content

Commit 03c12d0

Browse files
Merge pull request #15 from justinpbarnett/bug/material-saving
material saving fix
2 parents 9edb03d + c2be2bf commit 03c12d0

File tree

2 files changed

+80
-19
lines changed

2 files changed

+80
-19
lines changed

Editor/Commands/MaterialCommandHandler.cs

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using Newtonsoft.Json.Linq;
33
using UnityEngine.Rendering.Universal;
44
using UnityEngine.Rendering;
5+
using UnityEditor;
6+
using System.IO;
57

68
namespace MCPServer.Editor.Commands
79
{
@@ -22,26 +24,72 @@ public static object SetMaterial(JObject @params)
2224
// Check if URP is being used
2325
bool isURP = GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset;
2426

25-
// Create material with appropriate shader based on render pipeline
26-
Material material;
27-
if (isURP)
27+
Material material = null;
28+
string materialName = (string)@params["material_name"];
29+
bool createIfMissing = (bool)(@params["create_if_missing"] ?? true);
30+
string materialPath = null;
31+
32+
// If material name is specified, try to find or create it
33+
if (!string.IsNullOrEmpty(materialName))
2834
{
29-
material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
35+
// Ensure Materials folder exists
36+
const string materialsFolder = "Assets/Materials";
37+
if (!Directory.Exists(materialsFolder))
38+
{
39+
Directory.CreateDirectory(materialsFolder);
40+
}
41+
42+
materialPath = $"{materialsFolder}/{materialName}.mat";
43+
material = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
44+
45+
if (material == null && createIfMissing)
46+
{
47+
// Create new material with appropriate shader
48+
material = new Material(isURP ? Shader.Find("Universal Render Pipeline/Lit") : Shader.Find("Standard"));
49+
material.name = materialName;
50+
51+
// Save the material asset
52+
AssetDatabase.CreateAsset(material, materialPath);
53+
AssetDatabase.SaveAssets();
54+
}
55+
else if (material == null)
56+
{
57+
throw new System.Exception($"Material '{materialName}' not found and create_if_missing is false.");
58+
}
3059
}
3160
else
3261
{
33-
material = new Material(Shader.Find("Standard"));
62+
// Create a temporary material if no name specified
63+
material = new Material(isURP ? Shader.Find("Universal Render Pipeline/Lit") : Shader.Find("Standard"));
3464
}
3565

36-
if (@params.ContainsKey("material_name")) material.name = (string)@params["material_name"];
66+
// Apply color if specified
3767
if (@params.ContainsKey("color"))
3868
{
39-
var colorArray = (JArray)@params["color"] ?? throw new System.Exception("Invalid color parameter.");
40-
if (colorArray.Count != 3) throw new System.Exception("Color must be an array of 3 floats [r, g, b].");
41-
material.color = new Color((float)colorArray[0], (float)colorArray[1], (float)colorArray[2]);
69+
var colorArray = (JArray)@params["color"];
70+
if (colorArray.Count < 3 || colorArray.Count > 4)
71+
throw new System.Exception("Color must be an array of 3 (RGB) or 4 (RGBA) floats.");
72+
73+
Color color = new Color(
74+
(float)colorArray[0],
75+
(float)colorArray[1],
76+
(float)colorArray[2],
77+
colorArray.Count > 3 ? (float)colorArray[3] : 1.0f
78+
);
79+
material.color = color;
80+
81+
// If this is a saved material, make sure to save the color change
82+
if (!string.IsNullOrEmpty(materialPath))
83+
{
84+
EditorUtility.SetDirty(material);
85+
AssetDatabase.SaveAssets();
86+
}
4287
}
88+
89+
// Apply the material to the renderer
4390
renderer.material = material;
44-
return new { material_name = material.name };
91+
92+
return new { material_name = material.name, path = materialPath };
4593
}
4694
}
4795
}

Python/tools/material_tools.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from mcp.server.fastmcp import FastMCP, Context
2-
from typing import List
2+
from typing import List, Optional
33
from unity_connection import get_unity_connection
44

55
def register_material_tools(mcp: FastMCP):
@@ -9,18 +9,22 @@ def register_material_tools(mcp: FastMCP):
99
def set_material(
1010
ctx: Context,
1111
object_name: str,
12-
material_name: str = None,
13-
color: List[float] = None,
12+
material_name: Optional[str] = None,
13+
color: Optional[List[float]] = None,
1414
create_if_missing: bool = True
1515
) -> str:
1616
"""
17-
Apply or create a material for a game object.
17+
Apply or create a material for a game object. If material_name is provided,
18+
the material will be saved as a shared asset in the Materials folder.
1819
1920
Args:
2021
object_name: Target game object.
21-
material_name: Optional material name.
22-
color: Optional [R, G, B] values (0.0-1.0).
22+
material_name: Optional material name. If provided, creates/uses a shared material asset.
23+
color: Optional [R, G, B] or [R, G, B, A] values (0.0-1.0).
2324
create_if_missing: Whether to create the material if it doesn't exist (default: True).
25+
26+
Returns:
27+
str: Status message indicating success or failure.
2428
"""
2529
try:
2630
unity = get_unity_connection()
@@ -63,14 +67,23 @@ def set_material(
6367
return f"Error: Color {channel} value must be in the range 0.0-1.0, but got {value}."
6468

6569
# Set up parameters for the command
66-
params = {"object_name": object_name}
70+
params = {
71+
"object_name": object_name,
72+
"create_if_missing": create_if_missing
73+
}
6774
if material_name:
6875
params["material_name"] = material_name
69-
params["create_if_missing"] = create_if_missing
7076
if color:
7177
params["color"] = color
7278

7379
result = unity.send_command("SET_MATERIAL", params)
74-
return f"Applied material to {object_name}: {result.get('material_name', 'unknown')}"
80+
material_name = result.get("material_name", "unknown")
81+
material_path = result.get("path")
82+
83+
if material_path:
84+
return f"Applied shared material '{material_name}' to {object_name} (saved at {material_path})"
85+
else:
86+
return f"Applied instance material '{material_name}' to {object_name}"
87+
7588
except Exception as e:
7689
return f"Error setting material: {str(e)}"

0 commit comments

Comments
 (0)