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

相关推荐
后天han1 小时前
vscode中launch.json中定义的编译文件名于生成的不一致修改
ide·vscode·编辑器
在嵌入式里摸爬滚打6 小时前
VScode远程连接Ubuntu报错问题分析
ide·vscode·编辑器
雪下的新火8 小时前
Unity-HDRP场景搭建-那山
经验分享·笔记·unity·游戏引擎·场景搭建
Jiezcode9 小时前
Unreal Engine ClassName Rule
c++·游戏·图形渲染·虚幻引擎
你也向往长安城吗9 小时前
基于 navmesh 的路径搜索技术剖析 (游戏、三维方向必看!!!)
javascript·游戏·游戏开发
郝学胜-神的一滴15 小时前
深度解析游戏引擎中的相机:视图矩阵
程序人生·unity·矩阵·游戏引擎·godot·图形渲染·虚幻
EnigmaCoder15 小时前
【Linux】Vim编辑器:从入门到高效使用
linux·运维·编辑器·vim
谷宇.1 天前
【Unity3D实例-功能-拔枪】角色拔枪(三)IK的使用-紧握武器
游戏·unity·c#·unity3d·游戏开发·游戏编程·steam
电报号dapp1191 天前
链游开发新篇章:融合区块链技术的游戏创新与探索
游戏·区块链