關於Unity自動生成材質球的問題
阿新 • • 發佈:2018-12-26
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; }}