【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,三种材质。效果图如下:
文章图片
下面我们将我们优化的图展示一下:
文章图片
对比上图我们可以看到Saved by batching减少了,Used Textures 较少了,Render Textures使用的纹理大小也较少了,虽然相对来说Draw Call增加了,但是由于Render Textures少了,我们的优化效果达到了,而且位置也没变,多种材质也没问题了,但是还有个问题,就是我们的Cube有三个是相同的,但是我们看其材质的效果图:
文章图片
相同的材质写了三次,这说明我们的程序还需要继续去优化,以上代码只要将其组合在一起就可以使用了,我们将在讲台优化系列三中继续优化我们的优化程序。
推荐阅读
- Android技术分享| 实现视频连麦直播
- Cocos2d-x《赵云要格斗》--虚拟摇杆控制精灵上下左右运动
- 如何用程序员的方式,营造七夕氛围感()
- iOS开发面试只需知道这些,技术基本通关!(block篇)
- Cocos2d-x《雷电大战》-双层地图无限滚动
- 如何从JavaScript中的字符串中剥离HTML(仅提取文本内容)
- 如何仅使用JavaScript获取客户端IP地址
- 如何根据文件的文件扩展名设置ACE编辑器模式
- 在Phaser.js中为游戏实现免费的触摸操纵杆