欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于Unity自动生成材质球的问题

程序员文章站 2022-06-10 20:58:49
...

1,发现问题

上周末发了一个版本,发现动态加载有明显的卡顿,于是通过Profile来查顿卡的原因,发现里面Shader.Parse的调用,占用时间非常高,进一步发现里面有不少默认的Standard材质,单纯一个默认材质就有4.8MB加载,每增加一个角色模型 就多加一个默认材质。   最可怕单个FBX它同时加载 默认材质 与我们项目自身的写的那个材质。

2,问题起因

MAX导出FBX会默认带一个材质球信息进去unity引擎,默认的命名为Default-Material 这个材质,最讨厌的一点它还是使用Standard材质!!

3,解决方法

做为美术的我开始找MAX导入插件里面 有没有剔除这个材质的方法,找了很久并没有发现这个选项,加上大量已经制作完成的角色模型 如果要全部重新导入修改太麻烦, 就开始直接想要用脚本一次性解决,替换成我想要的材质。

 [MenuItem("Assets/更改模型材质")]
    public static void ChangeModel()
    {
        Object[] objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
        for (int i = 0; i < objs.Length; i++)
        {
            Object obj = objs[i];
            string url = AssetDatabase.GetAssetPath(obj);
            if (string.IsNullOrEmpty(url))
                continue;
            string ext = Path.GetExtension(url);
            if (ext != ".fbx" && ext != ".FBX")
                continue;
            if (!ContainsPath(url))
                continue;


            ModelImporter modelImporter = ModelImporter.GetAtPath(url) as ModelImporter;
            modelImporter.importMaterials = true;
            modelImporter.materialLocation = ModelImporterMaterialLocation.External;
            modelImporter.materialName = ModelImporterMaterialName.BasedOnTextureName;
            modelImporter.materialSearch = ModelImporterMaterialSearch.Everywhere;


            AssetDatabase.ImportAsset(url);
            AssetDatabase.Refresh();


            obj = AssetDatabase.LoadAssetAtPath<Object>(url);


            GameObject go = obj as GameObject;


            Renderer[] skins = go.GetComponentsInChildren<SkinnedMeshRenderer>(true);


            if (skins.Length == 0)
            {
                skins = go.GetComponentsInChildren<MeshRenderer>(true);
            }


            if (skins.Length == 0)
                return;


            if (skins.Length > 1)
            {
            }


            Renderer renderer = skins[0];
            if (renderer.sharedMaterials != null && renderer.sharedMaterials.Length > 0)
            {
                for (int j = 0; j < renderer.sharedMaterials.Length; j++)
                {
                    Material mat = renderer.sharedMaterials[j];
                    if (mat != null)
                    {
                        mat.shader = Shader.Find("Character/Character");
                    }
                }
            }
        }
    }


}

这是办法之一

解决办法之二

就是不让它在unity生成材质球,或者生成一个材质 全部模型公用,将消耗降到最小,或者删除默认材质

 

   
public class FbxTools : AssetPostprocessor
{
    public static string DefaultMaterialPath = "Assets/Common/Materials/DefaultMaterial.mat";


    // 添加重新导入fbx的功能。
    [MenuItem("Assets/Fbx/Reimport all FBX")]
    public static void ReimportAllFBX()
    {
        var files = AssetDatabase.GetAllAssetPaths();
        foreach (var vv in files)
        {
            var vvLower = vv.ToLower();
            if (vvLower.EndsWith("fbx"))
            {
                AssetDatabase.ImportAsset(vv, ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceUpdate);
            }
        }
    }

//删除默认的材质球 方法
    /// <summary>
    /// 对于模型,删除共享材质,保证不会将包括Standard这样的材质打包到游戏中。
    /// </summary>
    /// <param name="model"></param>
    //public void OnPostprocessModel(GameObject model)
    //{
    //    Renderer[] renders = model.GetComponentsInChildren<Renderer>();
    //    if (null != renders)
    //    {
    //        foreach (Renderer render in renders)
    //        {
    //            render.sharedMaterials = new Material[render.sharedMaterials.Length];
    //        }
    //    }
    //}
AssetPostprocessor
void OnPreprocessModel() { ModelImporter modelImporter = assetImporter as ModelImporter; modelImporter.importMaterials = false; } Material OnAssignMaterialModel(Material material, Renderer renderer) { Debug.Log("Invalid Material Name: " + material.name); Material defaultMaterial = AssetDatabase.LoadAssetAtPath<Material>(DefaultMaterialPath); if (defaultMaterial == null) { defaultMaterial = new Material(Shader.Find("Unlit/Texture")); AssetDatabase.CreateAsset(defaultMaterial, DefaultMaterialPath); } return defaultMaterial; }}