过早优化是万恶之源”——Donald Knuth
        不少开发者在前期开发过程中对算法等类似的开销都甚少关心,而是更倾向于尽可能简单的解决某个问题,后面必要时再进行优化。这能极大加速开发进度,并保证代码简洁。但开发后期通常会出现的瓶颈就是图形资源,而优化图形渲染这一块比较有难度。
        本文将分享作者Lamebait在使用Unity5制作沙盘游戏过程中优化SkinnedMeshRenderers的相关步骤提供给大家参考。

第一次迭代——使用不带动画的网格

每个城市街区约有15个网格,首先最显著的问题就是不断被加载到游戏中Mesh数量。当街区数量增长到数百之后,DrawCall数量也飙升到大多硬件所不能承受之高。Unity支持网格批处理,能减少一部分DrawCall。但所有网格都是有动画的,所以这些网格用的是SkinnedMeshRenderer组件而非MeshRenderer,Unity不支持对SkinnedMeshRenderer进行批处理。

第二次迭代——SkinnedMeshRenderer.BakeMesh()

所有的建筑和树木都只在它们出现和消失的时候有渐入和渐出的动画,一旦稳定下来之后就是完全静止的了,那可否在此期间将它们变为MeshRenderer呢?
        如果使用带有MeshRenderer的无动画网格,通过开关选择使用MeshRenderer还是SkinnedMeshRenderer,结果可能会发现有几个网格与其SkinnedMeshRenderer的最终状态不太匹配,所以这条路不通。
        下图展示了SkinnedMeshRenderer的最终状态与静态网格本身的差别。

SkinnedMeshRenderer中有个BakeMesh()函数,功能是按照网格当前的动画状态创建网格数据快照,并输出这个网格数据用于其它地方。这样就可以将输出的新网格传给MeshRenderer然后享受自动批处理的功能。但事情并非如此简单。
        下面创建包含各种网格类型的字典,以便多个MeshRenderer可以共享同一个网格,然后让Unity进行批处理。不论何时增加了新的网格,它都会被烘焙出来并加到字典中。但这样会爱导致进行网格类型切换后网格的高度略微有点拉伸。这是因为建筑的缩放值不是0,以致SkinnedMeshRenderer输出的网格本身被缩放了一次,而这个网格在应用到GameObject上的时候由于GameObject本身的缩放值又被缩放了一次。解决这种矛盾的办法就是先将建筑的缩放值设为1,烘焙后再设回原始值。
        到此整个切换看起来完全无缝。但这是有代价的,因为Unity也不支持对使用了阴影的MeshRenderer进行批处理。而关闭阴影又会对游戏效果大打折扣,所以必须想想其它办法。

第三次迭代——网格合并

还可以手动批处理,因为网格是可以合并成一张大网格的。当然也有些限制,如网格材质必须相同,单个网格的三角形数量有限等。还好这个游戏的建筑和树木总共才用到了三种不同的材质,所以可以将整个街区合并成最多三张大网格。
        基本上,创建CombineInstance后将BakeMesh()输出的网格传给它并加上Transform。最重要的是确保Transform的变换矩阵中GameObject本身的缩放值都是无效的,否则网格会像上文提到那样错误变形。合并后网格的最终结果会应用到网格之前所在的GameObject,然后在街区状态变为静止后移除。
        整个过程比较棘手。游戏中很多因素都会导致奇怪的效果,对于每个因素及每个可能的组合都要单独测试。但结果证明这是值得的,现在游戏在有阴影的情况下帧率也非常可观!
        合并的红色网格如下图:

第四次迭代——更高一级

这游戏设计的特色之一就是每个阵营最终的街区都会在生成之后被保留,所以如果街区从未改变过,可以将它们合并到一起。一个个合并会遭遇前面提过的网格大小限制。而将城市分为几个格子可以将几个街区的网格合并为单个,从而进一步降低DrawCall。效果如下图:

总结

本文最重要的三点:

  • 不要过早优化,可以适当晚一点。
  • 善于发现漏洞!如果某个东西不适用于X,那能否暂时将它变为Y呢?
  • 用创造性的技巧换取性能。

内容下载链接:
       https://github.com/Ryxali/StateCapital

在Unity 5中优化SkinnedMeshRenderer的更多相关文章

  1. Unity优化方向——优化Unity游戏中的图形渲染(译)

    CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...

  2. 【Unity优化】如何实现Unity编辑器中的协程

    Unity编辑器中何时需要协程 当我们定制Unity编辑器的时候,往往需要启动额外的协程或者线程进行处理.比如当执行一些界面更新的时候,需要大量计算,如果用户在不断修正一个参数,比如从1变化到2,这种 ...

  3. 【Unity优化】怎样实现Unity编辑器中的协程

    Unity编辑器中何时须要协程 当我们定制Unity编辑器的时候,往往须要启动额外的协程或者线程进行处理.比方当运行一些界面更新的时候,须要大量计算,假设用户在不断修正一个參数,比方从1变化到2.这种 ...

  4. Unity优化方向——优化Unity游戏中的垃圾回收(译)

    介绍 当我们的游戏运行时,它使用内存来存储数据.当不再需要该数据时,存储该数据的内存将被释放,以便可以重用.垃圾是用来存储数据但不再使用的内存的术语.垃圾回收是该内存再次可用以进行重用的进程的名称. ...

  5. Unity 几种优化建议

    转: http://user.qzone.qq.com/289422269/blog/1453815561?ptlang=2052 Unity 几种优化建议 最简单的优化建议: 1.PC平台的话保持场 ...

  6. 通过profiler对unity进行针对性优化

    转 : http://user.qzone.qq.com/289422269/blog/1453815629?ptlang=2052 通过profiler对unity进行针对性优化  1. CPU U ...

  7. i3D的一篇Unity教程中的笔记

    原地址:http://blog.sina.com.cn/s/blog_72b936d80100wwej.html 以下是i3D的一篇Unity教程中的笔记. i3D的这篇教程是[i3D.Next-Ge ...

  8. Unity 绘图性能优化 - Draw Call Batching

    Unity 绘图性能优化 - Draw Call Batching Unity官方链接:http://docs.unity3d.com/Manual/DrawCallBatching.html 转载请 ...

  9. Unity UI性能优化技巧

    本文将介绍一些提升Unity UI性能的技巧.更多优化技巧,可以观看Unity工程师Ian Dundore在Unite Europe 2017的演讲<使用Unity性能提升技巧>. 1.划 ...

随机推荐

  1. webUploader大文件断点续传学习心得 多文件

    二.Jsp代码: <!-- 断点续传   start--> <!-- 隐藏域 实时保存上传进度 --> <input id="jindutiao" t ...

  2. HDU5126 stars(cdq分治)

    传送门 题意: 先有两种操作,插入和查询,插入操作则插入一个点\((x,y,z)\),查询操作给出两个点\((x_1,y_1,z_1),(x_2,y_2,z_2)\),回答满足\(x_1\leq x\ ...

  3. vue - 基础(2)

    <div id="content"> {{ msg }} <div v-text="msg"></div> <div ...

  4. acwing 算法面试、笔试题公开课整理记录

    week1 Google KickStart 2019 A轮 讲解视频地址AcWing 549. 训练   tag: 排序 遍历 在线练习地址AcWing 550. 包裹       在线练习地址Ac ...

  5. scrapy框架--?乱码unicode

    安装 pip install scrapy 建立一个爬虫项目 scrapy startproject 项目名称 scrapy startproject itcast 进入itcast文件夹 生成一个爬 ...

  6. 导入数据任务(id:373985)异常, 错误信息:解析导入文件错误,请检查导入文件内容,仅支持导入json格式数据及excel文件

    小程序导入,别人导出的数据库json文件,错误信息如下: 导入数据库失败, Error: Poll error, 导入数据任务(id:373985)异常,错误信息:解析导入文件错误,请检查导入文件内容 ...

  7. 洛谷 P5535 【XR-3】小道消息

    https://www.luogu.com.cn/problem/P5535 伯特兰-切比雪夫定理: 若整数n > 3,则至少存在一个质数p,符合n < p < 2n − 2. 另一 ...

  8. Kafka Rebalance机制分析

    什么是 Rebalance Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有 consumer 如何达成一致,来分配订阅 Topic 的每个分区. 例如:某 G ...

  9. JavaScriptDOM编程学习笔记(一)DOM概述

    首先介绍下DOM,一套对文档的内容进行抽象和概念化的方法.即Document Object Model,当创建了一个网页并加载到Web浏览器中时,DOM就把编写的网页转换为一个文档对象,而通过浏览器提 ...

  10. Mysql 查看连接数,状态 最大并发数,以及设置连接数

    show variables like '%max_connections%'; 查看最大连接数 set global max_connections=1000  重新设置最大连接数 set-vari ...