Unity3D一键替换shader,生成有混合材质模型对应材质的shader并替换

本文介绍了如何使用UnityEditor工具,针对混合材质模型,通过遍历和创建Shader材质球,实现一键替换所有物体的材质。步骤包括导入模型、生成Editor菜单、定义工具栏、判断文件夹、遍历处理材质等。
摘要由CSDN通过智能技术生成


前言

本期内容为写好了对应的shader,以上期写的材质透明度修改的shader为例,然后拿到一个模型后,此模型为混合材质,并且有很多个物体,将所有的材质文件获取到对应的贴图文件,制作成对应的shader材质球进行一键替换。本功能为UnityEditor工具的一个使用。


一、UnityEditor是什么?

UnityEditor是Unity3D中的编辑器工具,可以在编辑模式下对自己的资源文件进行快速的操作,大幅度节省了工作量。

二、使用步骤

1.导入模型

将FBX格式的模型和对应的贴图导入到Unity3Dd的资源文件中。

2.实现流程

1、生成Editor菜单工具箱

首先生成一个Eidtor菜单栏工具箱

[MenuItem("OtherTools/ChangeMaterial")]

在这里插入图片描述
在这里会生成对应的工具栏。

2、定义工具栏大小和位置

然后定义一下点击这个按钮进行弹出的对话框的大小

    public static void Open()
    {
        EditorWindow window = GetWindow(typeof(ChangeMaterial));
        window.position = new Rect(Screen.width / 2, Screen.height / 2, 400, 80);
    }

这个的大小是400*80的框,位置在屏幕中间。

3、定义工具栏里面的元素

然后再定义这个弹框中的内容,在这里定义了两个可拖入的框,一个是物体,一个是shader,目的是将来把这个物体下所有的子物体的所有的材质做成拥有此shader的材质球并替换。

private static GameObject changeGame;
private static Shader changeShader;
private void OnGUI()
{
    changeGame = EditorGUILayout.ObjectField(changeGame, typeof(GameObject), true, GUILayout.MinWidth(100f)) as GameObject;
    changeShader = EditorGUILayout.ObjectField(changeShader, typeof(Shader), true, GUILayout.MinWidth(100f)) as Shader;

    if (GUILayout.Button("模型以及子模型Material替换脚本图片"))
    {
        Change();
    }
}

4、判断存放材质的文件夹是否存在

判断文件夹是否存在,如果存在的话就把新的材质文件放到此路径,如果不存在则创建对应文件夹,在对应路径中按照模型名称创建对应的shader材质文件夹。

 //判断文件夹是否存在
 string str_filePath = "Assets/Resources/Material/AotoMaterial/" + changeGame.name;
 Debug.Log(str_filePath);
 if (Directory.Exists(str_filePath))
 {
     Debug.Log("文件已存在");
 }
 else
 {
     Directory.CreateDirectory(str_filePath);
     Debug.Log("文件不存在,创建文件夹"+ str_filePath);
 }

5、对模型两次遍历生成替换材质

此时是两次遍历,第一次遍历是将模型和模型子物体遍历,找出所有的物体,第二次遍历是子物体中的所有材质球进行遍历,对每一个材质球进行处理。然后将每一个物体下的新的材质球放到list中,等子物体遍历结束后进行材质替换。

 List<Material> materialsOneGame;
 Dictionary<string, Material> materialsDic = new Dictionary<string, Material>();
 //遍历选择的物体下所有MeshRender
 //(true)表示可以将隐藏的物体也获取到
 MeshRenderer[] chlidMeshCollection = changeGame.GetComponentsInChildren<MeshRenderer>(true);

 foreach (var childMesh in chlidMeshCollection)
 {
     materialsOneGame = new List<Material>();
     //每一个MeshRender进行处理:遍历Material
     for (int i = 0; i < childMesh.sharedMaterials.Length; i++)
     { 
         //每一个material进行处理:获得mainMaps的图片
         //在对应路径下新生成一个材质球,材质球为指定shader脚本,材质球的图片为mainMaps的图片
         Texture materialTexture = childMesh.sharedMaterials[i].mainTexture;
         if (materialsDic.TryGetValue(materialTexture.name, out Material mat))//创建过对应的材质球
         {
             Debug.Log("创建过" + materialTexture.name);
         }
         else//没有创建过对应的材质球
         {
             //创建mat
             mat = new(changeShader)
             {
                 mainTexture = materialTexture,
                 name = materialTexture.name
             };
             //创建的mat材质放到Assets文件夹下
             AssetDatabase.CreateAsset(mat, "Assets/Resources/Material/AotoMaterial/" + changeGame.name + "/" + materialTexture.name + ".mat");
             materialsDic.Add(materialTexture.name, mat);
         }
         materialsOneGame.Add(mat);
     }
     childMesh.materials = materialsOneGame.ToArray();
     materialsOneGame.Clear();
 }
 materialsDic.Clear();

6、写完代码后Editor的使用

代码写完毕后,在菜单页打开对应的功能窗口,此窗口也可以和其他的scene、game窗口等合并,会出现三个部件,将需要替换材质的模型、需要替换挂载的shader脚本拖入,然后点击按钮进行生成就可以了。
在这里插入图片描述

3.完整代码

using DG.Tweening.Plugins.Core.PathCore;
using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEditor;
using UnityEngine;

#if UNITY_EDITOR
public class ChangeMaterial : EditorWindow
{
    [MenuItem("OtherTools/ChangeMaterial")]
    public static void Open()
    {
        EditorWindow window = GetWindow(typeof(ChangeMaterial));
        window.position = new Rect(Screen.width / 2, Screen.height / 2, 400, 80);
    }
    private static GameObject changeGame;
    private static Shader changeShader;

    private void OnGUI()
    {
        changeGame = EditorGUILayout.ObjectField(changeGame, typeof(GameObject), true, GUILayout.MinWidth(100f)) as GameObject;
        changeShader = EditorGUILayout.ObjectField(changeShader, typeof(Shader), true, GUILayout.MinWidth(100f)) as Shader;

        if (GUILayout.Button("模型以及子模型Material替换脚本图片"))
        {
            Change();
        }
    }
    public static void Change()
    {
        if (changeGame == null || changeShader == null)
        {
            Debug.Log("请填写完整");
            return;
        }
        //判断文件夹是否存在
        string str_filePath = "Assets/Resources/Material/AotoMaterial/" + changeGame.name;
        Debug.Log(str_filePath);
        if (Directory.Exists(str_filePath))
        {
            Debug.Log("文件已存在");
        }
        else
        {
            Directory.CreateDirectory(str_filePath);
            Debug.Log("文件不存在,创建文件夹"+ str_filePath);
        }
        List<Material> materialsOneGame;
        Dictionary<string, Material> materialsDic = new Dictionary<string, Material>();
        //遍历选择的物体下所有MeshRender
        //(true)表示可以将隐藏的物体也获取到
        MeshRenderer[] chlidMeshCollection = changeGame.GetComponentsInChildren<MeshRenderer>(true);

        foreach (var childMesh in chlidMeshCollection)
        {
            materialsOneGame = new List<Material>();
            //每一个MeshRender进行处理:遍历Material
            for (int i = 0; i < childMesh.sharedMaterials.Length; i++)
            { 
                //每一个material进行处理:获得mainMaps的图片
                //在对应路径下新生成一个材质球,材质球为指定shader脚本,材质球的图片为mainMaps的图片
                Texture materialTexture = childMesh.sharedMaterials[i].mainTexture;
                if (materialsDic.TryGetValue(materialTexture.name, out Material mat))//创建过对应的材质球
                {
                    Debug.Log("创建过" + materialTexture.name);
                }
                else//没有创建过对应的材质球
                {
                    //创建mat
                    mat = new(changeShader)
                    {
                        mainTexture = materialTexture,
                        name = materialTexture.name
                    };
                    //创建的mat材质放到Assets文件夹下
                    AssetDatabase.CreateAsset(mat, "Assets/Resources/Material/AotoMaterial/" + changeGame.name + "/" + materialTexture.name + ".mat");
                    materialsDic.Add(materialTexture.name, mat);
                }
                materialsOneGame.Add(mat);
            }
            childMesh.materials = materialsOneGame.ToArray();
            materialsOneGame.Clear();
        }
        materialsDic.Clear();
    }
}
#endif

总结

以上就是今天要讲的内容,本次讲解了对于混合材质模型进行shader材质创建并替换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兮途途

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值