在Unity 5中优化SkinnedMeshRenderer
过早优化是万恶之源”——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的更多相关文章
- Unity优化方向——优化Unity游戏中的图形渲染(译)
CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...
- 【Unity优化】如何实现Unity编辑器中的协程
Unity编辑器中何时需要协程 当我们定制Unity编辑器的时候,往往需要启动额外的协程或者线程进行处理.比如当执行一些界面更新的时候,需要大量计算,如果用户在不断修正一个参数,比如从1变化到2,这种 ...
- 【Unity优化】怎样实现Unity编辑器中的协程
Unity编辑器中何时须要协程 当我们定制Unity编辑器的时候,往往须要启动额外的协程或者线程进行处理.比方当运行一些界面更新的时候,须要大量计算,假设用户在不断修正一个參数,比方从1变化到2.这种 ...
- Unity优化方向——优化Unity游戏中的垃圾回收(译)
介绍 当我们的游戏运行时,它使用内存来存储数据.当不再需要该数据时,存储该数据的内存将被释放,以便可以重用.垃圾是用来存储数据但不再使用的内存的术语.垃圾回收是该内存再次可用以进行重用的进程的名称. ...
- Unity 几种优化建议
转: http://user.qzone.qq.com/289422269/blog/1453815561?ptlang=2052 Unity 几种优化建议 最简单的优化建议: 1.PC平台的话保持场 ...
- 通过profiler对unity进行针对性优化
转 : http://user.qzone.qq.com/289422269/blog/1453815629?ptlang=2052 通过profiler对unity进行针对性优化 1. CPU U ...
- i3D的一篇Unity教程中的笔记
原地址:http://blog.sina.com.cn/s/blog_72b936d80100wwej.html 以下是i3D的一篇Unity教程中的笔记. i3D的这篇教程是[i3D.Next-Ge ...
- Unity 绘图性能优化 - Draw Call Batching
Unity 绘图性能优化 - Draw Call Batching Unity官方链接:http://docs.unity3d.com/Manual/DrawCallBatching.html 转载请 ...
- Unity UI性能优化技巧
本文将介绍一些提升Unity UI性能的技巧.更多优化技巧,可以观看Unity工程师Ian Dundore在Unite Europe 2017的演讲<使用Unity性能提升技巧>. 1.划 ...
随机推荐
- 树莓派初入门(1):SSH远程登录与VNC远程桌面
前言: 本文主要讲解,对于一个无树莓派显示屏,无键盘,无鼠标,手边只有手机,电脑和一个已烧录好raspbian-stretch系统的树莓派3B+的玩家,如何进行远程登录,进而可以进程桌面的连接. 工具 ...
- 【转】Pandas学习笔记(二)选择数据
Pandas学习笔记系列: Pandas学习笔记(一)基本介绍 Pandas学习笔记(二)选择数据 Pandas学习笔记(三)修改&添加值 Pandas学习笔记(四)处理丢失值 Pandas学 ...
- Alibaba Cloud SDK for Java,知识点
资料 网址 Alibaba Cloud SDK for Java https://help.aliyun.com/document_detail/52740.html?spm=a2c4g.111742 ...
- centos安装安全狗5步就能完成
安全狗是为服务器开发的一款服务器管理软件,客户的服务器是centos 64位,我们就来看看如何安装吧.首先必须得有root账号权限,不然下面的步骤可能都无法执行.随ytkah一起来操作吧 1.下载安全 ...
- nginx 搭建上传服务器
nginx webdav 服务器搭建 该模块可以为Http webDAV 增加PUT,DELETE,MKCOL,COPY和MOVE等方法.模块在默认编译的情况下是不被包含的,需要指定编译 ./conf ...
- eclipse IDE for java developers下载与安装
1.进入eclipse官网下载页面 https://www.eclipse.org/downloads/ 2.点击Download Packages 3.windows 用户 选择 64 bits 4 ...
- C# 不包含 AsEnumerable 的定义
引用 System.Data.DataSetExtensions 引用右键 ->添加引用 ->搜索 DataSetExtensions ->添加 注意版本
- Qt常用类——QFrame类与QWidge类
QFrame与QWidget的区别: QFrame是基本控件的基类,QWidget是QFrame基类. QWidget类是所有用户界面对象的基类. Widget是用户界面的基本单元:它从窗口系统接收鼠 ...
- Solr的核心操作案例
@Service public class SearchServiceImpl implements SearchService { @Autowired private SolrTemplate s ...
- nginx设置防盗链
1.一般的防盗链设置: location ~* \.(gif|jpg|png|jpeg)$ { expires 30d; valid_referers none blocke *.julyy.site ...