查看: 1689|回复: 4
打印 上一主题 下一主题

[经验分享] Unity3D优化静态对象系列二

[复制链接]

100

主题

3

听众

7683

积分

高级设计师

Rank: 6Rank: 6

纳金币
2378
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2015-2-2 22:56:24 |只看该作者 |倒序浏览

在系列一中,我们已经知道了问题所在,一个是优化后我们模型位置改变了,另一个是如果是不同的材质的物体一起优化的时候,不同的材质的对象会消失掉,我们在系列二中主要是解决这两个问题:

    接下来我们改进的思路是查找所有的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>();

                // Handle bad input
                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)
                            break;
                    }

                    if (materialArrayIndex == materials.Count)
                    {
                        materials.Add(meshRenderer.sharedMaterials);
                        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有三个是相同的,但是我们看其材质的效果图:




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


分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

2722

主题

42

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
38266
精华
111

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2015-2-2 23:35:45 |只看该作者
文字是出啥问题啊
回复

使用道具 举报

无效楼层,该帖已经被删除

20

主题

5

听众

1090

积分

助理设计师

Rank: 4

纳金币
105
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2015-2-5 11:45:27 |只看该作者

Thanks for sharing this one !
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-5-4 07:49 , Processed in 0.089333 second(s), 29 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部