從優化角度,Mesh需要合並。
從換裝的角度(這里指的是換形狀、換組成部件的換裝,而不是掛點型的換裝),都需要網格合並、材質合並。如果是人物的換裝,那么需要合並SkinnedMeshRenderer,並重刷對應的骨骼列表。網格合並后對模型的渲染可以降低GPU的負擔,但是經過測試發現,雖然網格合並了但是由於子物體網格的材質是不同的並沒有降低DrawCall,如果把材質改成相同的,Unity自身會進行批處理合並,所以DrawCall就會減少!在MMO的游戲中,網格動態合並還是非常有必要的!
網格合並代碼:
private void CombineMesh() { //獲取自身和所有子物體中所有的 MeshRenderer 組件 MeshRenderer[] meshRenderers = GetComponentsInChildren<MeshRenderer>(); //材質球數組 Material[] materials = new Material[meshRenderers.Length]; for (int i = 0; i < meshRenderers.Length; i++) { materials[i] = meshRenderers[i].sharedMaterial; } // 合並 Mesh // 后去自身和子物體中所有 MsehFilter 組件 MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>(); CombineInstance[] combines = new CombineInstance[meshRenderers.Length]; for (int i = 0; i < meshFilters.Length; i++) { combines[i].mesh = meshFilters[i].sharedMesh; // 矩陣(Matrix)自身空間坐標的點轉換成世界空間坐標的點 combines[i].transform = meshFilters[i].transform.localToWorldMatrix; meshFilters[i].gameObject.SetActive(false); } //重新生成mesh MeshFilter meshFilter = transform.GetComponent<MeshFilter>(); if (meshFilter == null) { meshFilter = gameObject.AddComponent<MeshFilter>(); } // 給 MeshFilter 組件的 mesh 賦值 meshFilter.mesh = new Mesh(); //合並Mesh, 第二個參數 false,表示並不合並為一個網格,而是一個自網格列表 transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combines, false); transform.gameObject.SetActive(true); //為合並后的新Mesh 指定材質 //transform.GetComponent<MeshRenderer>().sharedMaterials = materials; MeshRenderer meshRender = transform.GetComponent<MeshRenderer>(); if (meshRender == null) { meshRender = gameObject.AddComponent<MeshRenderer>(); } meshRender.sharedMaterials = materials; }
運行前:
合並之后:
發現合並之后,三個子物體的材質都在父物體上,材質合並到了一個MeshRender下。
工程地址:git@git.oschina.net:wuzhang/UnityCombineMeshRender.git