0x00 前言

最近和朋友聊天,谈到了Mesh的内存优化问题,他发现开启Model Importer面板上的Mesh Compression选项之后,内存并没有什么变化。事实上,期望开启Mesh Compression后Mesh所占用的内存降低,是对Mesh Compression的作用的误解。

我相信很多同学看到Mesh Compression这个名字之后,也会有类似的误解。因此这篇博客就来聊一聊在Unity中如何对Mesh进行优化,以达到节约内存的目的,并且为何开启了Mesh Compression选项反而对内存没有什么帮助。

0x01 Unity中的Mesh压缩

在Unity中,主要有三种方式用来优化mesh数据的空间开销。

即Player Setting中的:

Vertex Compression

Optimize Mesh Data

以及Model importer中的:

Mesh Compression 

其中,Vertex Compression的实现是将顶点channel的数据格式format设置为16bit,因此可以节约运行时的内存使用(float->half)。

Optimize Mesh Data则主要用来剔除不需要的channel,即剔除额外的数据。因为与压缩无关,本文先暂时不讨论这个选项。

但是,Mesh Compression是使用压缩算法,将mesh数据进行压缩,结果是会减少占用硬盘的空间,但是在runtime的时候会被解压为原始精度的数据。

和Runtime时内存关系较大的是Vertex Compression的实现。

而是否可以进行Vertex Compression,则和模型的导入设置以及是否可以进行dynamic batching(在build 阶段,主要判断mesh的顶点数是否符合条件)有关。

简单可以归纳为以下几点:

1. 是否适合进行dynamic batching

2. 在Model Importer中是否开启了Read/Write Enabled

3. 在Model Importer中是否开启了Mesh Compression(是的,很吃惊是吧)

其中第一点,就是该mesh是否适合进行dynamic batching。这里不仅和player setting中是否勾选了dynamic batching有关,还和mesh的顶点数是否超过300有关。当然,dynamic batching是否可行主要和顶点属性的数量有关,但是为了简单,build阶段就按照常见的一个顶点带3个顶点属性,也就是300个顶点来做限制了。

所以如果开启了dynamic batching,则300个顶点以下的mesh不会被执行顶点压缩。

其次,Read/Write Enabled这个选项也会使Vertex Compression失效。所以一般情况下,为了节约内存最好不好勾选这个选项,除了无法进行顶点压缩之外,它还会额外在内存中保留一份mesh数据。

再次,也是大家常常忽略的一点,即如果开启了Mesh Compression,则会override掉Vertex Compression以及Optimize Mesh Data的设置 。Mesh Compression会将mesh在硬盘上的存储空间进行压缩,但是不会在runtime时节省内存。

0x02 测试

下面我们就通过几个小例子,来直观地查看一下各种设置下Mesh的内存占用情况。

Unity Version 2018.2.1

Windows Player

情况1:

默认情况,不开启压缩(MeshCompression和vertex compression),不开启Read/Write Enabled

Model Importer:

Building_e:

MeshCompression Off

Read/Write Enabled Off

Rock_c:

MeshCompression Off

Read/Write Enabled Off

Player Setting:

Dynamic Batching Off

vertex compression:None

Optimize Mesh Data:Off

测试结果:

Building_e 0.5mb

Rock_c 3.3kb

题外话:如果开启了Dynamic Batching,则Rock_c这个模型即便不开启Read/Write Enabled,其的内存占用也会更多,会达到5.9kb,这是因为对于顶点数较少(300以下)的模型,在开启动态合批的情况下我们会多保留一份它的mesh数据,即和Read/Write Enabled开启的效果是一样的。

情况2:

测试只开启vertex compression的情况。

Model Importer:

Building_e:

MeshCompression Off

Read/Write Enabled Off

Rock_c:

MeshCompression Off

Read/Write Enabled Off

Player Setting:

Dynamic Batching Off

vertex compression:Everything

Optimize Mesh Data:Off

测试结果:

Building_e 379.8kb

Rock_c 2.6kb

此时压缩生效。

情况3:

测试开启vertex compression 和 dynamic batching 的情况。

Model Importer:

Building_e:

MeshCompression Off

Read/Write Enabled Off

Rock_c:

MeshCompression Off

Read/Write Enabled Off

Player Setting:

Dynamic Batching On

vertex compression:Everything

Optimize Mesh Data:Off

测试结果:

Building_e 379.8kb

Rock_c 5.9kb

可以看到,Rock_c的内存占用升高了。这是因为Rock_c的顶点数只有40+,并且index buffer的format是16bit,在开启dynamic batching的情况下Build时被认为是符合动态合批条件的,因此在构建时不会执行vertex compression的操作。

因此在开启动态合批时,对一些小模型(vertex count<300)Vertex Compression是无效的。并且,这样的模型同样会保留在cpu可访问的内存中,以备动态合批的需要。

情况4:

测试开启vertex compression 和 dynamic batching 以及Read/Write Enabled的情况。

Model Importer:

Building_e:

MeshCompression Off

Read/Write Enabled On

Rock_c:

MeshCompression Off

Read/Write Enabled On

Player Setting:

Dynamic Batching On

vertex compression:Everything

Optimize Mesh Data:Off

测试结果:

Building_e 1.0mb

Rock_c 5.9kb

可以看到,此时Building_e的内存不仅没有被压缩变小,反而由于开启了Read/Write Enable而翻倍了。而Rock_c由于之前说过的原因,显示的也是翻倍后的内存占用。

所以,为了保证vertex compression能够正常的执行,减小runtime时mesh的内存占用,不要开启 Read/Write Enable。

情况5:

测试开启vertex compression 和 dynamic batching 以及Mesh Compression的情况。

我想最让人迷惑的可能就是Mesh Compression这个选项。从字面理解,这个选项的开启是对模型进行压缩的意思。但是实际上开启这个选项只会减小mesh在硬盘的存储大小,在runtime时vertex使用format并没有被改变,仍然是Float。因此也就无法实现Runtime时内存的优化。

Model Importer:

Building_e:

MeshCompression On

Read/Write Enabled Off

Rock_c:

MeshCompression On

Read/Write Enabled Off

Player Setting:

Dynamic Batching On

vertex compression:Everything

Optimize Mesh Data:Off

测试结果:

Building_e 0.5mb

Rock_c 5.9kb

让人吃惊的来了,Vertex Compression失效了。开启了Mesh Compression之后,内存回到了没有压缩时的数值。

0x03 结论

之所以勾选Mesh Compression后会有这个结果的原因,在上文已经描述了很多。

因此,一个小建议就是如果为了优化Mesh的内存开销,不要开启Mesh Compression,以避免Vertex Compression的失效。

Unity的Mesh压缩:为什么我的内存没有变化?的更多相关文章

  1. Unity中Mesh分解与边缘高亮加上深度检测

    一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...

  2. 关于Unity中Mesh网格的详解

    3D模型 通过3D建模软件所建出来的点和面,如以三角形为主的点和面,比如人的脑袋一个球,就是由各种各样的三角形组成的点和面. 点和面以及纹理坐标都是通过3D建模软件建模出来的. Unity会帮我们把模 ...

  3. Unity移动游戏加载性能和内存管理-学习笔记

    前言 正在学习Doctor 张.鑫大佬的移动游戏加载性能和内存管理,内容非常非常的干,所以我烧了很多开水,边喝边看,一边拿小本几做好笔记 本文只是关于前2章的内容笔记,关于各种资源的加载耗时 纹理资源 ...

  4. unity, 获取mesh名称

    正确的获取mesh名称的方法: MeshFilter meshFilter=node.GetComponent<MeshFilter>();    string meshName=mesh ...

  5. UNITY引擎变量调用产生不必要内存分配

    https://unity3d.com/de/learn/tutorials/topics/performance-optimization/optimizing-garbage-collection ...

  6. unity, editable mesh

    一,需求 从fbx载入的模型是不可以在unity里编辑的. 我有一人特殊的需求就是想在unity里为mesh的各顶点K动画. 于是需要自己实现一个可编辑(其实只是顶点可以拖动)的mesh. 二,思路 ...

  7. 史林枫:sqlserver数据库中数据日志的压缩及sqlserver占用内存管理设置

    使用sqlserver和IIS开发.net B/S程序时,数据量逐渐增多,用户也逐渐增多,那么服务器的稳定性就需要维护了.数据库如何占用更小内存,无用的日志如何瞬间清空? 今天在给一个客户维护网站的时 ...

  8. unity中mesh属性的uv坐标讨论

    http://blog.sina.com.cn/s/blog_427cf00b0102vp0j.html 之前在做连连看游戏中,也用到贴图坐标,当时我们讲到,不管是平铺(Tiling)还是偏移(Off ...

  9. Unity使用 16bit 压缩 Texture 颜色能均匀过渡

    下面是unity自带 16bit 图 的效果,可以看到颜色过度的很不均匀,占用内存 0.5M    如果调成 truecolor 后 颜色过渡很均匀,而内存却占到 1.1 M    讲图片 后缀名改成 ...

随机推荐

  1. Centos下的apache2练习

    前言: 我上星期一直在写代码忘记写博客了,明天回去补回来.脚本主要用于收集信息 今天刚刚学完apache.来做个总结,写的不好请多多指指出. 目标: Centos6.5的IP:192.168.1.21 ...

  2. 《Systems Performance》阅读笔记及收获

    本文共三部分: 笔记之前的废话是和书结缘的过程: Systems Performance笔记是正文,记录了读书笔记以及一些实践: 一些优化记录将之前做的一些优化归纳起来,同时也能反思做的如何,加入跟G ...

  3. MySQL,简单了解下、

    第一章 数据备份与导入导出 1.1.备份基本概念介绍 1.2.mysqldump详解 1.3.mydumper浅析 1.4.MySQL物理备份基本操作 1.5.了解mysqlpump工具 1.6.数据 ...

  4. 【基于url权限管理 shiro(一)】--基础

    只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源.权限管理包括用户认证和授权两部分.   用户认证 1.概 ...

  5. MVC下 把数据库中的byte[]值保存成图片,并显示在view页面

    MVC下 把数据库中的byte[]值转成图片,并显示在view页面 controller中的action方法 //显示图片[AllowAnonymous]public ActionResult Sho ...

  6. Go缓存DNS

    Go里面的DNSclient没有带任何的缓存,语言层面没有任何的缓存,但是我们可以通过下面这样的代码来 这样当我们调用http.Client的时候就会采用这个缓存的ip了,里面用到的dnscache是 ...

  7. bzoj 2038 小z的袜子 莫队

    莫队大法好,入坑保平安 只要能O(1)或O(log)转移,离线莫队貌似真的无敌. #include<cstdio> #include<iostream> #include< ...

  8. BZOJ_4773_负环_倍增弗洛伊德

    BZOJ_4773_负环 Description 在忘记考虑负环之后,黎瑟的算法又出错了.对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得 环上的边权和为负数.保证图中不包含重边 ...

  9. Drrols规则引擎

    1.什么是规则引擎? 规则引擎是一种嵌套在应用程序中的组件,它实现了将业务规则从应用程序代码中分离出来.规则引擎使用特定的语法编写业务规则,规则引擎可以接受数据输入.解释业务规则.并根据业务规则做出相 ...

  10. WebP 在减少图片体积和流量上的效果如何?MIP技术实践分享

    作者 | Jackson 编辑 | 尾尾 不论是 PC 还是移动端,图片一直占据着页面流量的大头,在图片的大小和质量之间如何权衡,成为了长期困扰开发者们的问题.而 WebP 技术的出现,为解决该问题提 ...