illustrate
Recently, art colleagues have a need when sorting out model animations, that is, to select a part of the model and replace the material with the same material ball. This function is realized under the editor. Put the code at the end, simply record it.
train of thought
- First traverse the selection to get all the sub-objects;
- Get the corresponding components for each specific object
Mesh Renderer
; - Make a judgment on each
MeshRender
componentMaterials
, judge whether there is a material, and whether there are multiple materials; - Support the function of rollback after the replacement is successful;
Effect
Here is to call the corresponding method in the Transform component, because it is possible that the selected object does not have MeshRenderer
a component. Support for selecting multiple objects.
the code
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class HK_ReplaceMaterial : Editor
{
[MenuItem("CONTEXT/Transform/ReplaceMaterial")]
static void MaterialReplacing()
{
MaterialReplacingEditorPanel.ShowReplaceMaterials();
}
}
public class MaterialReplacingEditorPanel : EditorWindow
{
//要替换的材质
Material _material;
public static void ShowReplaceMaterials()
{
EditorWindow ReplaceMaterialsWindow = GetWindow<MaterialReplacingEditorPanel>("ReplaceMaterials");
ReplaceMaterialsWindow.Show();
}
private void OnGUI()
{
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Label("材质替换", GUILayout.Width(100f));
_material = EditorGUILayout.ObjectField(_material, typeof(Material), true) as Material;
GUILayout.EndHorizontal();
GUILayout.Space(10);
if (GUILayout.Button("替换"))
{
var selectionObjs = Selection.gameObjects;
if (_material == null)
{
EditorUtility.DisplayDialog("提醒", string.Format("当前没有选择任何材质"), "确定");
}
else if (selectionObjs.Length == 0)
{
EditorUtility.DisplayDialog("提醒", string.Format("当前没有选中物体"), "确定");
}
else if (EditorUtility.DisplayDialog("提醒", string.Format("是否将当前选中的物体全部替换材质?", _material.name), "确定", "取消"))
{
for (int i = 0; i < selectionObjs.Length; i++)
{
TraverseChild(selectionObjs[i]);
}
}
}
}
void TraverseChild(GameObject thisObject)
{
//回退
List<Object> obj = new List<Object>();
for (int i = 0; i < thisObject.GetComponentsInChildren<Renderer>(true).Length; i++)
{
if (thisObject == null)
continue;
else if (thisObject.GetComponentsInChildren<Renderer>(true)[i] == null)
continue;
else if (thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterial == null)
continue;
obj.Add(thisObject.GetComponentsInChildren<Renderer>(true)[i]);
}
Undo.RecordObjects(obj.ToArray(), "ds");
for (int i = 0; i < thisObject.GetComponentsInChildren<Renderer>(true).Length; i++)
{
if (thisObject == null)
continue;
else if (thisObject.GetComponentsInChildren<Renderer>(true)[i] == null)
continue;
else if (thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterial == null)
continue;
List<Material> materials = new List<Material>();
foreach (var j in thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterials)
{
materials.Add(_material);
}
thisObject.GetComponentsInChildren<Renderer>(true)[i].sharedMaterials = materials.ToArray();
}
}
}