The Unity editor implements one-click replacement of materials for selected objects

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

  1. First traverse the selection to get all the sub-objects;
  2. Get the corresponding components for each specific object Mesh Renderer;
  3. Make a judgment on each MeshRendercomponent Materials, judge whether there is a material, and whether there are multiple materials;
  4. 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 MeshRenderera component. Support for selecting multiple objects.
insert image description here
insert image description here

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();
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_44446603/article/details/128366765