Unity去除項目中Default-Material

項目中的預製件或者模型文件,去除不必要的依賴Default-Material。

一、什麼是Default-Material

Default-Material是Unity內置的材質,並且依賴Standard Shader。

如果一個物體依賴了這個材質,在場景中是會顯示成紫色方塊,並且在打包的時候編譯shader非常耗時,並且會造成大量的冗餘。

所有這完全是一個沒要必要引用的東西,可以使用工具檢查項目,並且達到一鍵去除的功能。

二、查找項目中的Default-Material

在這裏首先要感謝Unity 查找unity內置資源的工具這篇博文博主提供的查找代碼。

引用到項目後,做了進一步的精簡,需要的是查找引用了Default-Material的資源。

整體思路:

0.使用編輯器常用接口,去查找文件,並且列舉出來。常用接口可以查看我的這邊文章Unity總結整理編輯器常用接口

1.搜索項目資源目錄中的.prefab和.fbx文件,預製件和模型文件

2.判斷文件上的Renderer是否有引用了Default-Material的材質,用名字匹配即可

3.按照預製件、模型文件,分別用不同的方式去除文件。

三、去除預製件上的Default-Material

找到預製件上的renderer,檢查是否引用了Default-Material,重新賦值一個空的材質,然後保存這個資源。

這裏需要注意的是不能直接render.sharedMaterials = null,或者mats [i] = null。

void RemoveDefaultMaterial(string path)
{
    GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
    Renderer[] renders = obj.GetComponentsInChildren<Renderer>();
    if (renders == null) return;
    string materialName = "Default-Material";
    foreach (var render in renders)
    {
        Material[] mats = render.sharedMaterials;
        for (int i = 0; i < mats.Length; i++)
        {
            if (null != mats[i] && mats[i].name == materialName)
            {
                render.sharedMaterials = new Material[render.sharedMaterials.Length];
            }
        }
    }
    AssetDatabase.SaveAssets();
    AssetDatabase.Refresh();
}

四、去除模型上的Default-Material

把模型的Import Material去掉勾選,然後再去除Default-Material。

與美術約定,模型只需要網格即可,導入模型做成預製件,然後在預製件中依賴對應的shader即可。

用工具檢查到有問題的模型後,使用AssetDatabase.ImportAsset重新導入這個資源,然後在導入處理代碼中統一處理。

這樣在下次導入其他模型時,也會使用去除代碼。

注意:importMaterials=false這個會修改meta文件,受版本控制。而render.sharedMaterials = new Material[render.sharedMaterials.Length]不受版本控制,所以如果檢查到有問題,需要在打包機上執行。

public class RemoveDefaultMaterial : AssetPostprocessor
{
    void OnPreprocessModel()
    {
        ModelImporter modelImporter = assetImporter as ModelImporter;
        modelImporter.importMaterials = false;
    }

    void OnPostprocessModel(GameObject model)
    {
        Renderer[] renders = model.GetComponentsInChildren<Renderer>();
        if (renders == null) return;
        foreach (Renderer render in renders)
        {
            render.sharedMaterials = new Material[render.sharedMaterials.Length];
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章