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

相关推荐
江上闲人.12 小时前
Wardogs战犬\战狗Beta测试启动报错UE崩溃卡顿?解决方法来了
游戏·游戏引擎·虚幻·战犬·战狗·wardogs
带娃的IT创业者14 小时前
Emacs 31:一场静默而深刻的范式演进
编辑器·文本编辑器·开源软件·emacs·lisp·软件架构
雷电小将军15 小时前
诡秘之主手游占卜家序列加点 诡秘之主手游占卜家怎么加点
服务器·网络·游戏·电脑·玩游戏
●VON15 小时前
芯笺 Markdown:面向 HarmonyOS PC 的本地优先 Markdown 编辑器
华为·编辑器·harmonyos·鸿蒙
小贺儿开发16 小时前
Unity 程序员编曲花絮:汪峰《河流》细节修复
科技·学习·unity·程序员·音乐·demo·写代码
598866753@qq.com17 小时前
Unity UniText笔记
unity·unitext
杨丰玮41817 小时前
从零手写Java飞机躲障碍游戏|Swing绘图、鼠标跟随、计时器碰撞检测实战(五)
java·python·游戏·游戏引擎·图形渲染·动画·贴图
yangmu320318 小时前
《明末:渊虚之羽》1.7版百款MOD终极指南:硬核配置与保姆级安装教程
游戏
●VON20 小时前
芯稿 MarkDeck 使用指南:用 Markdown 写出可编辑的 PPT
华为·编辑器·powerpoint·harmonyos·鸿蒙
鼎艺创新科技1 天前
不依赖 UE/Unity:我们如何从零搭建一套国产三维 GIS 渲染引擎
人工智能·算法·unity·游戏引擎·三维电子沙盘