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

相关推荐
王维志2 分钟前
Unity Embedded Browser文档翻译
unity·c#
wangduqiang74726 分钟前
VSCode 下 PlatformIO 的使用
ide·vscode·编辑器
weixin_4428254027 分钟前
goland 配置自己定义的proto文件
编辑器
念念不忘 必有回响34 分钟前
Pygame模块化实战:从零构建Aliens射击游戏全流程(一)
python·游戏·pygame
ONLYOFFICE10 小时前
如何在ONLYOFFICE中使用OCR工具:轻松识别图片和PDF中的文字
编辑器·ocr·office
qiu_zhongya11 小时前
unity以战斗截图并加上微信二维码分享
unity
我是是是是是西红柿12 小时前
游戏中的展销系统使用的数据结构
数据结构·游戏
塔中妖15 小时前
【华为OD】数字游戏
算法·游戏·华为od
老纪的技术唠嗑局16 小时前
向量检索技术优化步骤详解——游戏公司智能客服与推荐系统落地OceanBase
游戏
德迅云安全杨德俊17 小时前
游戏盾:构筑网络安全防线,抵御DDoS攻击的解决方案
网络·安全·游戏·ddos