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

相关推荐
VidDown2 天前
VidDown 工具站:免费、本地优先的开发者工具箱
javascript·编辑器·音视频·视频编解码·视频
VidDown2 天前
显卡处理视频技术详解:从硬解码到 NVENC,GPU 如何让视频处理起飞?
javascript·编辑器·音视频·视频编解码·视频
两水先木示2 天前
【Unity3D】小游戏启动优化、发热优化、蒙皮网格优化
游戏
资源分享助手2 天前
杀戮尖塔2下载、Slay the Spire 2中文版、卡牌肉鸽游戏、杀戮尖塔2联机、杀戮尖塔2攻略
游戏
夜猫逐梦2 天前
【UE基础】03.蓝图与编辑器工作流
编辑器·ue·蓝图·ue编辑器
VidDown3 天前
视频帧率技术详解:从 24fps 到 120fps,帧率如何影响你的观看体验?
网络·网络协议·编辑器·音视频·视频编解码·视频
叶帆3 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
爱就是恒久忍耐3 天前
VSCode里如何比较2个branch
ide·vscode·编辑器
久数君3 天前
AI三维建模工具“造形家”:地理场景三维化的高效解决方案
unity·glb·ai算法·ai三维建模工具·地图框选·造形家·城市建筑模型
Swift社区3 天前
当 AI 接管游戏世界:鸿蒙游戏 Workspace Runtime 架构揭秘
人工智能·游戏·harmonyos