评论

收藏

Unity3D静态对象优化系列二

游戏开发 游戏开发 发布于:2021-06-27 16:19 | 阅读数:308 | 评论:0

  在系列一中,我们已经知道了问题所在,一个是优化后我们模型位置改变了,另一个是如果是不同的材质的物体一起优化的时候,不同的材质的对象会消失掉,我们在系列二中主要是解决这两个问题:
    接下来我们改进的思路是查找所有的MeshFilter,同时我们根据不同的材质对我们需要优化的对象进行分离。这就需要我们定义两个链表:
ArrayList materials = new ArrayList();
    ArrayList combineInstanceArrays = new ArrayList();</pre>下面我们开始遍历我们需要优化对象的MeshFilter和MeshRenderer,因为材质是与MeshRenderder相关联的代码如下:<pre class="brush:c#;toolbar:false">    foreach (GameObject obj in Objects)
    {
      if (!obj)
        continue;
MeshFilter[] meshFilters = obj.GetComponentsInChildren&lt;MeshFilter&gt;();
foreach (MeshFilter meshFilter in meshFilters)
      {
        MeshRenderer meshRenderer = meshFilter.GetComponent&lt;MeshRenderer&gt;();
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 &lt; meshFilter.sharedMesh.subMeshCount; s++)
        {
          int materialArrayIndex = 0;
          for (materialArrayIndex = 0; materialArrayIndex &lt; 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);
        }
      }
    }</pre>下面是针对MeshFilter的处理代码:<br /><pre class="brush:c#;toolbar:false">  {
      MeshFilter meshFilterCombine = gameObject.GetComponent&lt;MeshFilter&gt;();
      if (!meshFilterCombine)
        meshFilterCombine = gameObject.AddComponent&lt;MeshFilter&gt;();
Mesh[] meshes = new Mesh[materials.Count];
      CombineInstance[] combineInstances = new CombineInstance[materials.Count];
for (int m = 0; m &lt; 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);
      }
    }</pre>将其组合成一个Mesh,接下来也是最后一步创建Mesh Renderer并将材质赋值给它<pre class="brush:c#;toolbar:false">   {
      MeshRenderer meshRendererCombine = gameObject.GetComponent&lt;MeshRenderer&gt;();
      if (!meshRendererCombine)
        meshRendererCombine = gameObject.AddComponent&lt;MeshRenderer&gt;();
Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[];
      meshRendererCombine.materials = materialsArray;
    }
   }下面我们看一下优化前后有啥变化,首先我们用四个Cube和一个Sphere,三种材质。效果图如下: DSC0000.jpg
下面我们将我们优化的图展示一下: DSC0001.jpg 对比上图我们可以看到Saved by batching减少了,Used Textures 较少了,Render Textures使用的纹理大小也较少了,虽然相对来说Draw Call增加了,但是由于Render Textures少了,我们的优化效果达到了,而且位置也没变,多种材质也没问题了,但是还有个问题,就是我们的Cube有三个是相同的,但是我们看其材质的效果图: DSC0002.jpg 相同的材质写了三次,这说明我们的程序还需要继续去优化,以上代码只要将其组合在一起就可以使用了,我们将在讲台优化系列三中继续优化我们的优化程序。
关注下面的标签,发现更多相似文章