Unity3D编辑器扩展-物体批量替换设置材质

前言

下面是一个Unity编辑器扩展工具,可以批量替换场景中多个游戏对象的材质。这个工具提供了一个直观的界面,允许用户选择多个对象并快速替换它们的材质。

对惹,这里有一 个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!

功能特点

  • 批量选择多个游戏对象
  • 替换所有选定对象的材质
  • 可选择仅替换特定索引的材质
  • 支持撤销操作
  • 界面简洁直观

代码实现

复制代码
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;

public class BatchMaterialReplacer : EditorWindow
{
    private List<GameObject> selectedObjects = new List<GameObject>();
    private Material sourceMaterial;
    private Material targetMaterial;
    private int materialIndex = 0;
    private bool replaceAllMaterials = true;
    private Vector2 scrollPosition;

    [MenuItem("Tools/Batch Material Replacer")]
    public static void ShowWindow()
    {
        GetWindow<BatchMaterialReplacer>("Material Replacer");
    }

    private void OnGUI()
    {
        GUILayout.Label("批量材质替换工具", EditorStyles.boldLabel);
        EditorGUILayout.Space();

        // 选择对象区域
        EditorGUILayout.BeginVertical("box");
        GUILayout.Label("选择对象:", EditorStyles.boldLabel);
        
        if (GUILayout.Button("添加选中对象"))
        {
            AddSelectedObjects();
        }
        
        if (GUILayout.Button("清空列表"))
        {
            selectedObjects.Clear();
        }

        // 显示已选择的对象列表
        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(150));
        for (int i = 0; i < selectedObjects.Count; i++)
        {
            selectedObjects[i] = (GameObject)EditorGUILayout.ObjectField(
                $"对象 {i + 1}", selectedObjects[i], typeof(GameObject), true);
        }
        EditorGUILayout.EndScrollView();
        EditorGUILayout.EndVertical();

        EditorGUILayout.Space();

        // 材质设置区域
        EditorGUILayout.BeginVertical("box");
        GUILayout.Label("材质设置:", EditorStyles.boldLabel);
        
        sourceMaterial = (Material)EditorGUILayout.ObjectField(
            "原材质 (可选)", sourceMaterial, typeof(Material), false);
        
        targetMaterial = (Material)EditorGUILayout.ObjectField(
            "目标材质", targetMaterial, typeof(Material), false);
        
        replaceAllMaterials = EditorGUILayout.Toggle("替换所有材质", replaceAllMaterials);
        
        if (!replaceAllMaterials)
        {
            materialIndex = EditorGUILayout.IntField("材质索引", materialIndex);
        }
        EditorGUILayout.EndVertical();

        EditorGUILayout.Space();

        // 操作按钮
        EditorGUI.BeginDisabledGroup(targetMaterial == null || selectedObjects.Count == 0);
        if (GUILayout.Button("替换材质", GUILayout.Height(30)))
        {
            ReplaceMaterials();
        }
        EditorGUI.EndDisabledGroup();

        // 提示信息
        if (selectedObjects.Count == 0)
        {
            EditorGUILayout.HelpBox("请先添加一些游戏对象到列表中。", MessageType.Info);
        }
        else if (targetMaterial == null)
        {
            EditorGUILayout.HelpBox("请选择目标材质。", MessageType.Warning);
        }
    }

    private void AddSelectedObjects()
    {
        foreach (GameObject obj in Selection.gameObjects)
        {
            if (!selectedObjects.Contains(obj))
            {
                selectedObjects.Add(obj);
            }
        }
    }

    private void ReplaceMaterials()
    {
        if (targetMaterial == null) return;

        Undo.RecordObjects(selectedObjects.Where(obj => obj != null).ToArray(), "Replace Materials");

        int replacedCount = 0;

        foreach (GameObject obj in selectedObjects)
        {
            if (obj == null) continue;

            Renderer renderer = obj.GetComponent<Renderer>();
            if (renderer == null) continue;

            // 检查是否需要根据原材质过滤
            if (sourceMaterial != null)
            {
                bool hasSourceMaterial = replaceAllMaterials ? 
                    renderer.sharedMaterials.Any(m => m == sourceMaterial) : 
                    renderer.sharedMaterials.Length > materialIndex && 
                    renderer.sharedMaterials[materialIndex] == sourceMaterial;
                
                if (!hasSourceMaterial) continue;
            }

            // 替换材质
            if (replaceAllMaterials)
            {
                Material[] newMaterials = new Material[renderer.sharedMaterials.Length];
                for (int i = 0; i < newMaterials.Length; i++)
                {
                    newMaterials[i] = targetMaterial;
                }
                renderer.sharedMaterials = newMaterials;
                replacedCount++;
            }
            else if (materialIndex < renderer.sharedMaterials.Length)
            {
                Material[] newMaterials = renderer.sharedMaterials;
                newMaterials[materialIndex] = targetMaterial;
                renderer.sharedMaterials = newMaterials;
                replacedCount++;
            }
        }

        Debug.Log($"成功替换了 {replacedCount} 个对象的材质。");
    }
}

使用说明

  1. 在Unity编辑器中,通过菜单栏 Tools > Batch Material Replacer 打开工具窗口
  2. 在场景中选择一个或多个游戏对象,然后点击"添加选中对象"按钮
  3. 选择要替换的"目标材质"
  4. (可选) 如果需要只替换特定材质,可以设置"原材质"和"材质索引"
  5. 点击"替换材质"按钮执行替换操作

注意事项

  • 此工具会直接修改场景中对象的材质,建议在执行前保存场景
  • 支持撤销操作(Ctrl+Z)
  • 如果对象没有Renderer组件,将被自动跳过

这个工具可以大大提高在Unity中批量处理材质的工作效率,特别适用于需要为多个对象统一更换材质的场景。

更多教学视

Unity3D​www.bycwedu.com/promotion_channels/2146264125

相关推荐
电子云与长程纠缠1 天前
Blender入门学习05 - 材质
学习·blender·材质
ii_best1 天前
按键精灵安卓/iOS脚本辅助,OpenCV实现自动化高效率工具
ios·自动化·编辑器·安卓
yi碗汤园1 天前
【一文了解】八大排序-冒泡排序、选择排序
开发语言·前端·算法·unity·c#·1024程序员节
嘀咕博客1 天前
h5游戏免费下载:2048.0
游戏
工业相机定制与开发1 天前
几种常见的激光打标机及适配材质推荐选型
目标跟踪·视觉检测·材质
Hello123网站1 天前
h5游戏免费下载:读心术
游戏
qq_205279051 天前
unity PS 给图片换透明底图,去除白色底图
unity
我狸才不是赔钱货1 天前
VsCode + Wsl:终极开发环境搭建指南
ide·vscode·编辑器
AA陈超1 天前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-19 打开属性菜单
c++·游戏·ue5·游戏引擎·虚幻
向宇it1 天前
【推荐100个unity插件】unity易于使用模块化设计的天空、体积云和天气系统——Enviro 3
游戏·3d·unity·c#·游戏引擎