代码
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class ReplaceMaterial : Editor
{
public static GameObject thisObject;
public static Material newMaterial;
public static string oldMaterialName = "Roof_Red";
public static string newMaterialPath = "MaterialReplace/Roof_Orange";
[MenuItem("CONTEXT/Transform/ReplaceMaterial")]
static void MaterialReplacing()
{
newMaterial = Resources.Load<Material>(newMaterialPath);
thisObject = Selection.activeGameObject;
Debug.Log("正在替换" + thisObject.name + "中的指定材质");
TraverseChild(thisObject);
}
static void TraverseChild(GameObject thisObject)
{
for (int i = 0; i < thisObject.GetComponentsInChildren<Renderer>(true).Length; i++)
{
if (thisObject == null)
{
Debug.LogError("Error1");
continue;
}
else if (thisObject.GetComponentsInChildren<Renderer>(true)[i] == null)
{
Debug.LogError("Error2");
continue;
}
else if (thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterial == null)
{
Debug.LogError(thisObject.GetComponentsInChildren<Renderer>(true)[i].name + "Error3");
continue;
}
Debug.Log("遍历第" + i + "个子物体:" + thisObject.GetComponentsInChildren<Renderer>(true)[i].name);
bool tobeChanged = false;
foreach(var j in thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterials)
{
if (j.name == oldMaterialName)
tobeChanged = true;
}
if(tobeChanged)
{
List<Material> materials = new List<Material>();
foreach (var j in thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterials)
{
if (j.name == oldMaterialName)
{
Debug.Log("正在替换" + thisObject.name + "的材质:" +
j.name + "->" +
newMaterial.name);
materials.Add(newMaterial);
}
else
materials.Add(j);
}
thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterials = materials.ToArray();
}
}
}
}
使用方法
效果
替换前
替换中
替换后
常见问题:为什么材质无法替换?
可以替换sharedMaterial,也可以替换sharedMaterials,但是不能替换sharedMaterials[index]
这应该是一个比较常见的错误,就是说,sharedMaterial是get、set,sharedMaterials也是get、set,但是sharedMaterials[index]仅仅是get,就像如果要改变transform.position,必须x、y、z一起改变,不可以只改变x。
总结
其实一开始我也在这里卡住了很久,仔细看了很多遍,怎么看都不是逻辑的问题。
百度也查不到,但是上Google用英文一查,第一个就是答案。
Setting shared materials not working?
Q:
So, I try to assign material like
someObject.GetComponent<Renderer>().sharedMaterials[0] = coolMaterial
But it doesn't take. I've debugged it and the new material I am trying to assign it to is correct, and the object material remains the same after this line as before. It is an instanced clone, so I don't know if that has to do with it. I even tried .materials too.
A:
You can't assign each material individually: material, sharedMaterial sharedMaterials confusion - Unity Forum