04. 资源审查

这是摘自Unity官方文档有关优化的部分,原文链接:https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity.html
总共分为如下系列:

  1. 采样分析
  2. 内存部分
  3. 协程
  4. Asset审查
  5. 理解托管堆 【推荐阅读】
    5.1 上篇:原理,临时分配内存,集合和数组
    5.2 下篇:闭包,装箱,数组
  6. 字符串和文本
  7. 资源目录
  8. 通用的优化方案
  9. 一些特殊的优化方案

真实项目中大部分错误都是无心之过——临时的测试改动或者某个非常累的开发者不小心设置错了资源导入设置,造成资源出现大问题。

对于规模很大的项目,需要加入对抗人为错误的首条防线。例如,写几行代码确保没有人可以给工程提交了一个4K的未压缩纹理。你可能觉得很意外,但是这是一个非常常见的错误。一个4K的未压缩纹理会占据超过60MB的内存资源。在比较低端的设备上,例如iPhone4S上,超过180-200MB的内存就比较危险了。如果错误地添加了这个问题,1/4~1/3的内存就被占用了,也会造成非常难检测的内存溢出问题。

虽然在5.3之后,可以用内存剖析工具找到这个问题,但是还是最好在一开始就防止类似这样的问题发生。

使用AssetPostprocessor

Unity编辑器中的AssetPostprocessor类可以用来确定Unity工程中的资源是否满足标准。当资源被导入的时候,这个类会收到回调。使用这个类的方法只需要继承,自己实现多个OnPreprocess方法即可。重要的方法有:

  • OnPreprocessTexture
  • OnPreprocessModel
  • OnPreprocessAnimation
  • OnPreprocessAudio

具体可以参见AssetPostProcessor,可以知道更多的OnPreprocess方法。

public class ReadOnlyModelPostprocessor : AssetPostprocessor 
{
   public void OnPreprocessModel() 
   {
        ModelImporter modelImporter = (ModelImporter)assetImporter;
        if(modelImporter.isReadable) 
        {
            modelImporter.isReadable = false;
            modelImporter.SaveAndReimport();
        }
    }
}

上面是应用AssetPostprocessor的一个例子。

当项目中导入模型的时候或者模型的导入设置被更改的时候,这个方法会被调用。这个方法会检测Read/Write属性,如果属性为true,强制改成false,保存并且重新导入。

记住,SaveAndReimport方法会导致这个代码又被执行一次,因为会强制将属性改为false,所以不会进入到无限循环。

这个改动的原因可以参见模型部分。

常见的资源规则

纹理Texture

关闭read/write enabled的标志

Read/Write enabled标志导致Texture会在内存中存在两份资源:一份在GPU,一份在GPU寻址空间【因为在大部分平台,从GPU内存读取非常缓慢。从GPU内存读取纹理资源到临时缓冲区非常不划算】。在Unity中,这个选项默认被关闭,但是有可能被意外开启。

Read/Write enabled属性被打开只有在Shader外操作纹理数据才有意义(例如Texture.GetPixel和Texture.SetPixel等)所以应当尽可能避免开启。

尽可能关闭Mipmaps

如果对象相对于Camera的Z深度不变,最好关闭mipmaps可以节省大概1/3的内存。如果对象的Z深度值会变化,关闭mipmaps可能导致GPU的取样效果比较差。

通常来讲,UI纹理和在屏幕上是固定大小的纹理资源通过可以关闭掉mipmaps选项。

压缩所有的纹理

对于目标平台使用合理的纹理压缩格式可以节省内存资源。

如果目标平台的纹理压缩格式设置的不合理,Unity加载纹理资源之后会对纹理资源重新解压,会消耗大量CPU时间和内存资源。这对于Android设备很常见,通常是因为不同的芯片级支持不同的纹理格式,差异太大,难以统一。

建立纹理限制条件

虽然这个很简单,但是通常很容易忘记重新调整纹理的大小,或者不小心改变了导入设置中的纹理大小。最好是通过代码确定不同类型的纹理资源是否满足了设定的规则。

模型Model

关闭Read/Write enabled的标志

Read/Write enabled标志对于模型而言和Texture中的道理相同。但是,对于模型而言,Unity对于这个选项默认开启。

当项目会在运行过程中通过代码修改Mesh,或者Mesh被用来作为MeshCollider组件的基础时,Unity要求这个属性必须开启。如果模型没有用到MeshCollider中或者不需要通过代码修改,将这个属性改成false可以节省一半的内存资源。

对于非Character类的模型关闭rigs

默认情况下,Unity会为非Character模型导入一个原生的rig。这样会导致如果在运行过程中实例化这个模型,Animator组件会被添加。如果这个模型不需要通过Animation系统控制动画,就会增加额外的开销。因为所有处在活跃状态下的Animator会在每帧被触发。

对于不需要动画的模型最好关闭这个属性防止增加额外的Animator组件和场景中出现不需要的动画效果。

对于有动画效果的模型开启Optimize Game Objects选项

Optimize Game Object选项对于有动画的模型有非常大的性能影响。当这个选项被关闭之后,当模型被实例化的时候,Unity会创建一个大的Transform层级用来映射模型的骨架结构。这个transform的Update开销会非常大,尤其是有其他的组件(如例子系统或者碰撞器)挂接在上面的时候。这个属性同时也会影响Unity多线程处理蒙皮和骨骼动画运算的能力。

如果某个模型骨架的一部分需要被暴露出来,如某个模型的双手部分需要控制武器,那么这些部分可以列入Extra Transforms列表的白名单。

更多的细节可以参见Unity教程的模型导入部分。Model Importer

尽可能使用Mesh压缩

启用网格压缩之后,用来表示模型数据的不同频道的浮点数的位数会减少。这样虽然会引起精度的丢失,所以最终的效果需要被美术同学认可才能放入最终的工程中。

具体的浮点数的位数和压缩等级之间的关系可以参见Scripting API的ModelImporterMeshCompression.

需要注意的是,不同的频道可以使用不同的压缩等级,所以在项目中可以选择压缩切线和法线而不压缩UV和顶点位置。

注意:网格渲染的设置

当向Prefab或者GameObject添加网格渲染器的时候,需要注意设置问题。默认情况下,Unity会开启Shadow casting and receiving,Light Probe sampling,Reflecion Probe sampling和Motion Vector calculation。

如果项目中不需要使用到上面的这些特性,请用脚本确保上面的属性被关闭。任何执行添加MeshRender的运行代码也需要确定是否开启这些属性。

对于2D游戏而言,如果不小心向场景中加入的MeshRender中shadow选项未被关闭,会给渲染循环中加入额外的shadow pass过程,对于性能来讲是浪费。

音频

针对平台选择合适的压缩选项

确保对于硬件设备选择合适的压缩格式。所有的iOS设备硬件支持MP3解码,而很多Android设备原生支持Vorbis格式。

而且,向Unity中导入未压缩的音频格式,Unity当打包工程的时候会压缩这些音频文件。所以没有必要导入压缩的音频文件,然后又解压,这样只会降低最后音频的品质。

将音频强制改成单声道

很少移动设备有立体扬声器。在移动设备的工程里,将导入的音频强制改成单声道可以节省一半的资源消耗。对于不需要有立体声效果的音频也是同样处理,如UI声效。

降低音频码率

当然这个需要和负责音频部分的同事进行沟通,最大化降低音频文件的码率可以更进一步的减少内存消耗和打包的工程大小。

上篇:协程

下篇:理解托管堆...上

如果觉得文章对您有用,请点个赞呗!☺☺☺

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 111. [动画系统]如何将其他类型的动画转换成关键帧动画? 动画->点缓存->关键帧 112. [动画]Unit...
    胤醚貔貅阅读 12,984评论 3 90
  • This article is a record of my journey to learn Game Deve...
    蔡子聪阅读 3,768评论 0 9
  • 原文地址 http://www.fx114.net/qa-75-172454.aspx 使用Profiler工具...
    IongX阅读 5,837评论 1 11
  • 一、java程序的生命周期 二、JVM JVM是实现java语音与平台无关性的关键 JVM负责与操作系统的交互,用...
    by小杰阅读 304评论 0 0
  • 夜风吹着河边的柳树 枝条轻轻的摇 人来人往 脚步匆忙 谁也没注意到树下的男人 他闭着眼睛,也许已经睡着 手中的瓶子...
    攻心毒阅读 194评论 0 1