1. 程式人生 > >unity匯出的FBX引用default_mat的問題

unity匯出的FBX引用default_mat的問題

原文地址:http://www.jianshu.com/p/cc0410e0c31c

自己也遇到了這個問題,記錄一下。。

0. 寫在之前

本來創業之後,部落格都計劃整理成分量比較足、沉澱比較夠的內容來做,但在遊戲開發過程中,也不斷踩了Unity的很多小坑。它們不足以整理成條理清晰、內容豐富的部落格文章,但是填坑過程又花費了半天到一天的時間,如果記錄下來給猜到同樣坑的同學,也許就可以省去那麼一些時間,於是決定新開一個小的筆記系列——Unity填坑筆記,我簡單記錄,您快速檢視。

1. 起因

目前在做大世界的動態載入,載入的時候有明顯的頓卡,於是通過Profile來查頓卡的原因,發現有Shader.Parse的呼叫,佔用時間非常高,中低配機器上大約200ms+。
於是做了Shader的預編譯,提前WarmUp用到的Shader,再次打包測試,依然有Shader.Parse的呼叫,通過Sample記憶體的差異來看編譯了哪些Shader,其中有一大部分是Standard。


記憶體中有Standard的Shader

2. 原因

通過Profile右側的Referenced By,可以檢視當前的Asset被哪個東西引用,看了一下發現,都是被FBX引用了,匯入的FBX檔案中,都使用了Default-Material,而這個Default-Material是使用的Standard Shader。


FBX使用的Default-Material

3. 解決方法

這個Default-Material並不能被修改,於是我搜索了半天,找到一個外掛號稱可以支援替換Default-Material,夠買來看了下,用的是在AssetPostprocessor中OnAssignMaterialModel來替換材質的方法,例項程式碼供參考:

    protected virtual Material OnAssignMaterialModel(Material previousMaterial, Renderer renderer)
    {
        var materialPath = "Assets/Default_Materiall.mat";

        if (AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)))
        {
            return AssetDatabase.LoadAssetAtPath(materialPath, typeof
(Material)) as Material; } Debug.Log(previousMaterial.name); return previousMaterial; }

這樣只需要提供一個自定義的Default_Material.mat檔案,重新匯入所有的FBX檔案,就可以進行替換了。
另外一個種方法是UWA群裡的朋友提供了,就是刪除掉Defualt-Material,沿著這個思路搜尋了一下,發現網上已經有解決方案:刪除FBX的預設材質
示例程式碼如下:

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

注意這裡不能將sharedMaterials設定為null,而是要new一個空的列表給它。
給一個遍歷程式碼來處理所有的FBX檔案:

    // 新增重新匯入fbx的功能。
    [MenuItem("Assets/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);
            }
        }
    }

4. 坑

除了前面提到的Default-Material會導致按照AB打包可能重複載入Standard Shader,Unity 5.5.1f版本還有一個坑就是如果用了Remote的Cache Server,會導致AssetDatabase.ImportAsset不會更新內容,因為這個問題坑了我很久。。。因為右鍵直接ReImport是可以更新的,但是如果想Reimport All,會重新匯入貼圖,時間佔用非常多,因此一直想只處理fbx檔案,但是在Unity 5.5.1f版本中一直不太對,後來查到這個bug Report
可恨的是,我本地貌似呼叫前面寫的ReimportAllFBX方法會把Cache Server設定為Remote!雖然不能理解,但是現象貌似就是如此。。。
最後,升級了Unity版本到5.5.3f,依然關閉Cache Server,重新匯入所有的,可以了。
tips:可以通過Project中只顯示model來過濾檢視所有的模型是否都是粉色的來保證所有的Default-Material都被幹掉了。


驗證所有model都變粉了~