Unity 检查材质球依赖属性和所用shader属性不一致的材质球

一个材质球,直接切换shader的时候 , 如果原来有对应shader的贴图属性,当导出这个材质或者打包这个材质的时候,肯能会导出一些 表面上看起来没有用到的贴图
当我们来回切换材质球的shader的时候,我们会发现这个材质球都能同时切换到shader对应的贴图,这是因为这个材质存了所有的属性,当我们最后确定下来之后 ,要将这些没有用到的删去

步骤:
1、找到所有材质球
2、找出材质球shader的属性
2.1 、 ShaderUtil.GetPropertyCount(shader) shader属性个数
2.2 、 ShaderUtil.GetPropertyType(shader,index) shader属性类型
ShaderUtil.ShaderPropertyType,TexEnv 贴图属性
2.2 、 ShaderUtil.GetPropertyName(shader,index) shader属性名称
3、找出材质球的属性
3.1 SerializeObject so=bew SerualizeObejct(Object) 拿到Material 对应的序列化对象
3.2 var iter= so.GetItrerator() iter.NextVisiable(true)迭代器遍历属性
3.3 材质球的属性不太一样 对所有贴图属性的引用存放在一个数组里
3.4 m_TexEnvs.Array.size.是数组大小
3.5 m_TexEnvs.Array.data[i].second.m_Texture 是数组 的一条数据的贴图
3.6 m_TexEnvs.Array.data[i].first.name 是这个贴图在shader里的属性名称
3.7 当迭代到m_TexEnvs 这个属性时停止迭代 用iter.FinPropertyRelative(str) 相对路径进行查找属性
3.8 intValue objectReferenceValue stringValue
4、对比找到不用的属性
5、用Material.SetTexture(str,null) 将不用的贴图属性设置为空即可

代码:

using UnityEngine;
using System.Collections;
using UnityEditor;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
/// <summary>
///  用来检查材质换了shader之后 对原来属性仍有引用的的工具
/// </summary>
public class CheckMatShaderWindow : EditorWindow
{

    [MenuItem("Tools/检查/检查材质和shader参数不符的材质")]
    private static void CheckMat()
    {
        GetWindow<CheckMatShaderWindow>().Show();
        Check();
    }

    [MenuItem("Tools/检查/检查Hidden-InternalErrorShader的Material")]
    private static void FindErrorShader()
    {
        GetWindow<CheckMatShaderWindow>().Show();
        FindHiddenShader();
    }
    private static void FindHiddenShader()
    {
        flag = "ErrorShader";
        res.Clear();
       var mats= AssetDatabase.GetAllAssetPaths().Where(s => s.EndsWith("mat")).Select(s => AssetDatabase.LoadAssetAtPath<Material>(s));
        foreach (var item in mats)
        {
            if (item.shader.name.Contains("Error"))
            {
                res.Add(item, null);
            }
        }
        EditorUtility.DisplayDialog("", "就绪", "OK");
    }

    private static string flag = "";
    private static Dictionary<Material, Dictionary<string, UnityEngine.Object>> res = new Dictionary<Material, Dictionary<string, UnityEngine.Object>>();

    private static void Check()
    {
        flag = "Check";
        res.Clear();
        var allfiles = Directory.GetFiles("Assets/", "*.mat", SearchOption.AllDirectories);
        foreach (var file in allfiles)//遍历所有材质
        {
            Material tempMat = AssetDatabase.LoadAssetAtPath<Material>(file);
            string[] temp = GetTextureProperyOfShader(tempMat.shader);
            var resul = GetTextureProperyOfMaterial(tempMat).Where(s => !temp.Contains(s.Key)).ToDictionary(s=>s.Key,s=>s.Value);
            if (resul.Count != 0) res.Add(tempMat, resul);
        }
        EditorUtility.DisplayDialog("一共查找了" + allfiles.Length + "个材 质球", "就绪", "OK");
    }
    ///***********************************核心**********************************
    /// <summary>
    /// 获取一个材质的贴图属性 贴图不为空的属性
    /// </summary>
    /// <param name="m"></param>
    private static Dictionary<string,UnityEngine.Object> GetTextureProperyOfMaterial(Material m)
    {
        Dictionary<string, UnityEngine.Object> dic = new Dictionary<string, UnityEngine.Object>();
        SerializedObject so = new SerializedObject(m);
        var iter = so.GetIterator();
        while (iter.NextVisible(true))
        {
            if (iter.propertyPath.Contains("m_TexEnvs"))
            {
                for (int i = 0; i < iter.FindPropertyRelative("Array").FindPropertyRelative("size").intValue; i++)
                {
                    UnityEngine.Object o = iter.FindPropertyRelative("Array").FindPropertyRelative("data[" + i + "]").FindPropertyRelative("second").FindPropertyRelative("m_Texture").objectReferenceValue;
                    if (o != null)
                        dic.Add(iter.FindPropertyRelative("Array").FindPropertyRelative("data[" + i + "]").FindPropertyRelative("first").FindPropertyRelative("name").stringValue, o);
                }
                break;
            }
        }
        return dic;
    }
    /// <summary>
    /// 获取一个shader的贴图属性
    /// </summary>
    /// <param name="s"></param>
    /// <returns>结果</returns>
    private static string[] GetTextureProperyOfShader(Shader s)
    {
        List<string> t = new List<string>();
        for (int i = 0; i < ShaderUtil.GetPropertyCount(s); i++)
        {
            if (ShaderUtil.GetPropertyType(s,i) == ShaderUtil.ShaderPropertyType.TexEnv)
            {
                t.Add(ShaderUtil.GetPropertyName(s, i));
            }
        }
        return t.ToArray();
    }
    ///******************************************

    /// <summary>
    /// 清除多余的贴图属性
    /// </summary>
    private static void ClearPropery()
    {
        int count = 0;
        foreach (var item in res)
        {
            if (item.Key.shader.name.Contains("Error")) continue;
            foreach (var item2 in item.Value)
            {
                item.Key.SetTexture(item2.Key, null);
                count++;
            }
        }
       EditorUtility.DisplayDialog("完成", "一个清除" + count + "个属性", "OK");
        if (count != 0)
        {
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            Check();
        }
    }
    private Vector2 scro = Vector2.zero;
    private void OnGUI()
    {
        if (flag == "Check")
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Count:" + res.Count);
            if (GUILayout.Button("清除所有多余的属性")) ClearPropery();
            EditorGUILayout.EndHorizontal();
            scro = EditorGUILayout.BeginScrollView(scro);
            EditorGUILayout.BeginVertical();
            foreach (var item in res)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.ObjectField(item.Key, typeof(GameObject), true, GUILayout.Width(200));
                EditorGUILayout.BeginVertical();
                foreach (var o in item.Value)
                {
                    EditorGUILayout.BeginHorizontal();
                    GUILayout.Label(o.Key, GUILayout.Width(o.Key.Length * 10));
                    EditorGUILayout.ObjectField(o.Value, typeof(GameObject), true, GUILayout.Width(200));
                    EditorGUILayout.EndHorizontal();
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndScrollView();
        }else if (flag == "ErrorShader")
        {
            scro = EditorGUILayout.BeginScrollView(scro);
            EditorGUILayout.BeginVertical();
            foreach (var item in res)
            {
                EditorGUILayout.ObjectField(item.Key, typeof(GameObject), true, GUILayout.Width(200));
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndScrollView();
        }
    }
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值