Unity3D静态对象优化系列二

【Unity3D静态对象优化系列二】古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。这篇文章主要讲述Unity3D静态对象优化系列二相关的知识,希望能为你提供帮助。
      在系列一中,我们已经知道了问题所在,一个是优化后我们模型位置改变了,另一个是如果是不同的材质的物体一起优化的时候,不同的材质的对象会消失掉,我们在系列二中主要是解决这两个问题:

    接下来我们改进的思路是查找所有的MeshFilter,同时我们根据不同的材质对我们需要优化的对象进行分离。这就需要我们定义两个链表:

                ArrayList  materials  =  new  ArrayList();                 ArrayList  combineInstanceArrays  =  new  ArrayList();

下面我们开始遍历我们需要优化对象的MeshFilter和MeshRenderer,因为材质是与MeshRenderder相关联的代码如下:
                foreach  (GameObject  obj  in  Objects)                 {                         if  (!obj)                                 continue;                         MeshFilter[]  meshFilters  =  obj.GetComponentsInChildren< MeshFilter> ();                         foreach  (MeshFilter  meshFilter  in  meshFilters)                         {                                 MeshRenderer  meshRenderer  =  meshFilter.GetComponent< MeshRenderer> ();                                 if  (!meshRenderer)                                 {                                         Debug.LogError("MeshFilter  does  not  have  a  coresponding  MeshRenderer.");                                         continue;                                 }                                 if  (meshRenderer.materials.Length  !=  meshFilter.sharedMesh.subMeshCount)                                 {                                         Debug.LogError("Mismatch  between  material  count  and  submesh  count.  Is  this  the  correct  MeshRenderer?");                                         continue;                                 }                                for  (int  s  =  0;   s  <   meshFilter.sharedMesh.subMeshCount;   s++)                                 {                                         int  materialArrayIndex  =  0;                                         for  (materialArrayIndex  =  0;   materialArrayIndex  <   materials.Count;   materialArrayIndex++)                                         {                                                 if  (materials[materialArrayIndex]  ==  meshRenderer.sharedMaterials[s])                                                         break;                                         }                                        if  (materialArrayIndex  ==  materials.Count)                                         {                                                 materials.Add(meshRenderer.sharedMaterials[s]);                                                 combineInstanceArrays.Add(new  ArrayList());                                         }                                        CombineInstance  combineInstance  =  new  CombineInstance();                                         combineInstance.transform  =  meshRenderer.transform.localToWorldMatrix;                                         combineInstance.subMeshIndex  =  s;                                         combineInstance.mesh  =  meshFilter.sharedMesh;                                         (combineInstanceArrays[materialArrayIndex]  as  ArrayList).Add(combineInstance);                                 }                         }                 }

下面是针对MeshFilter的处理代码:

        {                         MeshFilter  meshFilterCombine  =  gameObject.GetComponent< MeshFilter> ();                         if  (!meshFilterCombine)                                 meshFilterCombine  =  gameObject.AddComponent< MeshFilter> ();                         Mesh[]  meshes  =  new  Mesh[materials.Count];                         CombineInstance[]  combineInstances  =  new  CombineInstance[materials.Count];                         for  (int  m  =  0;   m  <   materials.Count;   m++)                         {                                 CombineInstance[]  combineInstanceArray  =  (combineInstanceArrays[m]  as  ArrayList).ToArray(typeof(CombineInstance))  as  CombineInstance[];                                 meshes[m]  =  new  Mesh();                                 meshes[m].CombineMeshes(combineInstanceArray,  true,  true);                                 combineInstances[m]  =  new  CombineInstance();                                 combineInstances[m].mesh  =  meshes[m];                                 combineInstances[m].subMeshIndex  =  0;                         }                        meshFilterCombine.sharedMesh  =  new  Mesh();                         meshFilterCombine.sharedMesh.CombineMeshes(combineInstances,  false,  false);                         foreach  (Mesh  mesh  in  meshes)                         {                                 mesh.Clear();                                 DestroyImmediate(mesh);                         }                 }

将其组合成一个Mesh,接下来也是最后一步创建Mesh Renderer并将材质赋值给它
      {                         MeshRenderer  meshRendererCombine  =  gameObject.GetComponent< MeshRenderer> ();                         if  (!meshRendererCombine)                                 meshRendererCombine  =  gameObject.AddComponent< MeshRenderer> ();                         Material[]  materialsArray  =  materials.ToArray(typeof(Material))  as  Material[];                         meshRendererCombine.materials  =  materialsArray;                 }         }

下面我们看一下优化前后有啥变化,首先我们用四个Cube和一个Sphere,三种材质。效果图如下:
Unity3D静态对象优化系列二

文章图片



下面我们将我们优化的图展示一下:
Unity3D静态对象优化系列二

文章图片

对比上图我们可以看到Saved by batching减少了,Used Textures 较少了,Render Textures使用的纹理大小也较少了,虽然相对来说Draw Call增加了,但是由于Render Textures少了,我们的优化效果达到了,而且位置也没变,多种材质也没问题了,但是还有个问题,就是我们的Cube有三个是相同的,但是我们看其材质的效果图:
Unity3D静态对象优化系列二

文章图片

相同的材质写了三次,这说明我们的程序还需要继续去优化,以上代码只要将其组合在一起就可以使用了,我们将在讲台优化系列三中继续优化我们的优化程序。

    推荐阅读