文章目录
前言
本期内容为写好了对应的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材质创建并替换。