1. 程式人生 > >關於Unity自動生成材質球的問題

關於Unity自動生成材質球的問題

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; }}