资源类型与导入
- 外部导入资源
- 模型网格Mesh
- 纹理
- 音乐音效
- 字体
- 动画
- 视频
- 内部创建资源
- Prefab
- Animation Controller
- Timeline
- RenderTexture
- ParticleSystem
- VFX
- 内部创建资源也需要考虑不同平台设置以及第三方package导入
资源设置检查
- Unity UPR 工具:https://upr.unity.cn
- 这里用的是Asset Checker
- 在UPR后台看资源检测报告
- 报告会给出一系列优化建议,下面篇章会解读这些建议的作用
Audio导入优化
- 双通道音频如果左右声道一致,建议开启Force To Mono选项来节省内存(会变成单声道)
- 建议导入未压缩的wav格式音频,通过unity内针对不同平台的压缩方法控制压缩率
- 大多数移动平台选用Vorbis格式
- 苹果平台对Mp3格式有优化,不循环的音频也可以选mp3
- 简短常用音效可以用ADPCM格式,虽然压缩率不高,但解码速度很快
- PCM为未压缩格式
- 移动平台采样率不宜过高,会徒增内存和文件占用(推荐22050hz),unity内可以覆盖采样率
- 音频加载类型
- Decompress On Load,一般建议压缩音频后大小小于200kb的音效文件使用
- Compressed in Memory,一般建议对于复杂音效,大小大于200kb,长度超过5秒的音效使用
- Streaming,一般推荐背景音乐文件或长度较长的音效文件,不容易卡顿
- Audio Source组件当需要静音时可以直接销毁,减少内存占用,而不是简单设置音量为0
- 优化音频文件一般可以节省内存占用和安装包文件大小,对性能影响较小(stream加载会增加一点点cpu开销)
优化前后真机对比(Android)
- Apk包体由原来的560.7M下降到544.6M
- Audio部分的内存由76.1M下降到6.9M
- CPU开销由2.5%左右上升到5%左右,这是由于部分音频资源才用了Streaming模式加载
Model导入设置检查与优化
Unity模型导入流程
DCC中模型导出
- Unity 支持多种标准和专有模型文件格式(DCC)。Unity 内部使用 .fbx 文件格式作为其导入链。最佳做法尽可能使用 .fbx 文件格式,并且不应在生产中使用专有文件格式。
- 优化原始导入模型文件,删除不需要的数据
- 统一单位
- 导出的网格必须是多边形拓扑网格,不能是贝塞尔曲线、样条曲线、NURBS、NURMS、细分曲面等
- 烘培Deformers,在导出之前,确保变形体被烘培到网格模型上,如骨骼形变烘培到蒙皮权重上
- 不建议模型使用到的纹理随模型导出,会降低引擎导入资源效率以及资源目录变得难管理
- 如果你需要导入blend shape normals,必须要指定光滑组smooth groups
- DCC导出面板设置, 不建议携带场景信息导出,如不建议导出摄像机、灯光、材质等信息,因为这些的信息与Unity内默认都不同。除非你自己为某DCC做过自定义导出插件。
原始模型文件对性能的影响点(美术制作开发标准)
- 最小化面数(尽量不要通过增加面数来加强细节),不要使用微三角形(在编辑器中多观察,指的是一个三角面只包含个位数像素,如果出现了需要用lod或让美术进行调节),分布尽量均匀
- 对性能的影响:微三角面会增加绘制的三角形数量,从而增加GPU的工作量,降低渲染性能。
- 对内存的影响:微三角面需要占用更多的内存空间,因为它会增加网格数据的大小。
- 对贴图的影响:微三角面会使得UV贴图变得更加复杂,导致UV贴图的失真和变形。
- 对物理引擎的影响:微三角面会对物理引擎的性能和稳定性造成影响。
- 合理的网络拓扑和平滑组,尽可能形成闭包,而不是没有焊接的面去组合。会导致产生额外的三角形和边,以及可能会引起引擎烘焙错误
- 尽量少的使用材质个数
- 尽可能少的使用蒙皮网格
- 尽可能少的骨骼数量
- FK与IK节点分离,导出时删除IK骨骼节点,因为unity不支持
模型导入设置中的一些选项
- Scene中关于Import的选项,一般没有特殊需求可以不开启
- Meshes网格设置
- Mesh Compression,会节省磁盘空间,但不会节省内存空间,适合激进的情况,需要观察开启后是否正常运行,开启此选项要尽可能使模型制作规范,最好是闭包模型
- Read/White,开启后会增加一个副本,一份在内存一份在显存,只有需要运行时修改模型才建议开启,skinmesh也需要开启(否则动画会出问题)
- Optimize Mesh和Generate Colliders一般保持默认,除非要禁止优化或者需要网格级别碰撞
- Geometry设置
- Index Format :如果确认网格顶点数不超过65535,可以使用十六位索引
- Normal、Tangents相关设置:印象中与法线光滑有关,如果要模型描边可以用。不需要法线、切线时可以关闭
- 光照第二套uv生成:如果不需要光照烘焙可以关闭
模型优化
- 尽可能的将网格合并到一起
- 尽可能使用共享材质
- 不要使用网格碰撞体
- 不必要不要开启网格读写
- 使用合理的LOD级别
- Skin Weights受骨骼影响个过多
- 合理压缩网格
- 不需要rigs和BlendShapes尽量关闭
- 如果可能,禁用法线或切线
- 多套模型
FBX部分问题解读
- 其中两项建议与模型动画有关,而测试项目中所有模型资源都不涉及动画,可以将Rig标签下的Animation Type设置为None,并关闭Animation标签下的Import Animations选项,设置Materials标签中的Material Creation Mode为None.
- 开启Project Settings——>Player——>Optimization下的Vertex Compression与Optimize Mesh Data选项
- Vertex Compression:设置每个通道的顶点压缩,可为位置、光照贴图uv之外的数据启用
- Optimize Mesh Data:根据网格使用的材质删除不需要的数据,如材质如果没有使用法线、颜色、uv等信息
优化成果
- 包体大小前后没变化,依然是544.6M
- 运行时模型内存优化前为422.9M,优化后为400.5M,相差的22M来自于运行时CombinedMesh开销的节省。后期运行时模型资源优化才是我们的重点。
纹理导入设置与优化
Texture基础概念介绍
纹理类型
类型(*号为常用) | 描述 |
---|---|
*Default | 默认的纹理类型格式,绝大多数资源使用这个 |
*Normal map | 法线贴图,可将颜色通道转换为适合实时法线贴图格式 |
Editor GUI and Legacy GUI | 在编辑器GUI控件上使用纹理请选择此类型 |
*Sprite(2D and UI) | 在2D游戏中使用的精灵(Sprite)或UGUI使用的纹理请选择此类型 |
Cursor | 鼠标光标自定义纹理类型 |
Cookie | 用于光照Cookie剪影类型的纹理 |
*Lightmap | 光照贴图类型的纹理,编码格式取决于不同的平台(平台不支持或设置不对可能会导致精度丢失) |
*Single Channel | 如果原始图片文件只有一个通道,请选择此类型,可以节省纹理内存开销 |
纹理大小
现代显卡一般要求纹理长宽为2的幂次方,unity默认会将其转为最小2的幂次方大小。
纹理的大小会影响内存和显存的占用,以及gpu采样纹理时的性能、cpu加载和带宽造成影响
选择合适纹理大小应尽量遵循以下经验:
- 不同平台、不同硬件配置选择不同的纹理大小,Unity下可以采用bundle变体设置多套资源、通过Mipmap限制不同平台加载不同level层级的贴图。
- 根据纹理用途的不同选择不同的纹理加载方式,如流式纹理加载Texture Streaming、稀疏纹理Sparse Texture、虚拟纹理VirtualTexture等方式。
- 不能让美术人员通过增加纹理大小的方式增加细节,可以选择细节贴图DetailMap或增加高反差保留的方式。
- 在不降低视觉效果的情况下尽量减小贴图大小,最好的方式是纹理映射的每一个纹素的大小正好符合屏幕上显示像素的大小,如果纹理小了会造成欠采样,纹理显示模糊,如果纹理大了会造成过采样,纹理显示噪点。这一点做到完美平衡很难保障。
- builtin管线可以充分利用Unity编辑器下SceneView->DrawMode->Mipmap来查看在游戏摄像机视角下哪些纹理过采样,哪些纹理欠采样,进而来调整纹理大小。
- urp暂不支持,未来可能也许会放在Rendering debuger window里
纹理颜色空间
- 默认大多数图像处理工具都会使用sRGB颜色空间处理和导出纹理。但如果你的纹理不是用作颜色信息的话,那就不要使用sRGB空间,如金属度贴图、粗糙度贴图、高度图或者法线贴图等。一旦这些纹理使用sRGB空间会造成视觉表现错误。
- 这部分与伽马校正有关
纹理压缩
-
纹理压缩是指图像压缩算法,保持贴图视觉质量的同时,尽量减小纹理数据的大小。默认情况下我们的纹理原始格式采用PNG或TGA这类通用文件格式,但与专用图像格式相比他们访问和采样速度都比较慢,无法通用GPU硬件加速,同时纹理数据量大,占用内存较高。所以在渲染中我们会采用一些硬件支持的纹理压缩格式,如ASTC 、ETC、ETC2、DXT等。(可以看一下技术美术百人计划相关章节)
-
如下图为未压缩、ETC2、ASTC6x6三种格式文件大小对比,我们可以看到在质量相差不大的情况下ASTC6x6压缩下大小可以减少到接近未压缩的十分之一。合理设置可以节省极大内存和空间
纹理图集
纹理图集是一系列小纹理图像的集合,Unity可以使多个网格对象对应一张纹理贴图,默认支持SpriteAtlas,但复杂模型还是需要美术同学在dcc软件中做好uv展开和uv映射
-
优点:
- 一是采用共同纹理图集的多个静态网格资源可以进行静态合批处理,减少DrawCall调用次数。
- 二是纹理图集可以减少碎纹理过多,因为他们打包在一个图集里,通过压缩可以更有效的利用压缩,降低纹理的内存成本和冗余数据。
-
缺点
- 美术需要合理规划模型,并且要求模型有相同的材质着色器,或需要制作通道图去区分不同材质。制作和修改成本较高。
纹理过滤
这部分可以看下GAMES101相关内容,往下递增性能开销成本上升,需要合适选择
过滤方式 | 具体作用 |
---|---|
Nearest Point Filtering | 临近点采样过滤最简单、计算量最小的纹理过滤形式,但在近距离观察时,纹理会呈现块状。 |
Bilinear Filtering | 双线性采样过滤会对临近纹素采样并插值化处理,对纹理像素进行着色。双线性过滤会让像素看上去平滑渐变,但近距离观察时,纹理会变得模糊。 |
Trilinear Filtering | 三线性过滤除与双线性过滤相同部分外,还增加了Mipmap等级之间的采样差值混合,用来平滑过度消除Mipmap之间的明显变化。 |
Anisotropic Filtering | 各向异性过滤可以改善纹理在倾斜角度下的视觉效果,跟适合用于地表纹理。 |
纹理Mipmap
Mipmap纹理
-
逐级减低分辨率来保存纹理副本。相当于生成了纹理LOD,渲染纹理时,将根据像素在屏幕中占据的纹理空间大小选择合适的Mipmap级别进行采样。是进行Hierarchical-Z Cull的前提条件
-
优点:
- GPU不需要在远距离上对对象进行全分辨率纹理采样,因此可以提高纹理采样性能。
- 同时也解决了远距离下的过采样导致的噪点问题,提高的纹理渲染质量。
-
缺点:
- 由于Mipmap纹理要生成低分辨率副本,会造成额外的内存开销。多1/3
- 可以使用unity的Mipmap streaming功能,在运行时限制只采样某个级别以下的纹理,进行不同设备的不同适配
Texture Shape
- 2D 最常用的2D纹理,默认选项
- Cube 一般用于天空和与反射探针,默认支持Default、Normal、Single Channel几种类型纹理,可以通过Assets > Create > Legacy > Cubemap生成,也可以通过C#代码 Camera.RenderToCubemap在脚本中生成
- 2D Array 2D纹理数组,可以极大提高大量相同大小和格式的纹理访问效率,但需要特定平台支持或特定图形api支持,可以通过引擎SystemInfo.supports2DArrayTextures 接口运行时查看是否支持。
- 3D 通过纹理位图方式存储或传递一些3D结构话数据,一般用于体积仿真,如雾效、噪声、体积数据、距离场、动画数据等信息,可以外部导入,也可运行时程序化创建。
Alpha Source
默认选择Input Texture Alpha就好,如果确定不使用原图中的Alpha通道,可以选择None。另外From Gray Scale我们一般不会选用
Alpha Is Transparency
指定Alpha通道是否开启半透明,如果位图像素不关心是否要半透明可以不开启此选项。这样Alpha信息只需要占1bit。节省内存
Ignore Png file gamma
是否忽略png文件中的gamma属性,这个选项是否忽略取决于png文件中设置不同gamma属性导致的显示不正常,一般原图制作流程没有特殊设置,这个选项一般默认就好。
Read/Write
开启此选项会导致内存量增加一倍,默认我们都是不开启,除非你的脚本逻辑中需要动态读写该纹理时需要打开此选项。
Streaming Mipmaps
一般是默认
Virtual Texture Only
一般是默认
Generate Mip Maps
- 什么时候不需要生成MipMaps?
- 2D场景
- 固定视角,摄像机无法缩放远近
- Border Mip Maps 默认不开启,只有当纹理的是Light Cookies类型时,开启此选项来避免colors bleeding现象导致颜色渗透到较低级别的Mip Level纹理边缘上
- MipMap Filtering
- Box 最简单,随尺寸减小,Mipmap纹理变得平滑模糊
- Kaiser,避免平滑模糊的锐化过滤算法。
- Mip Maps Preserve Coverage,只有需要纹理在开启mipmap后也需要做Alpha Coverage时开启。默认不开启。
- Fadeout MipMaps, 纹理Mipmap随Mip层级淡化为灰色,一般不开启,只有在雾效较大时开启不影响视觉效果。
选择合适纹理过滤的最佳经验:
- 使用双线性过滤平衡性能和视觉质量。
- 有选择地使用三线性过滤,因为与双线性过滤相比,它需要更多的内存带宽。
- 使用双线性和 2x 各向异性过滤,而不是三线性和 1x 各向异性过滤,因为这样做不仅视觉效果更好,而且性能也更高。
- 保持较低的各向异性级别。仅对关键游戏资源使用高于 2 的级别。
各平台的默认纹理压缩格式
其他可能有问题的纹理类型
- 纹理图集大小设置不合理,图集利用率低。
- 纹理生命周期不一致,应尽量将生命周期接近的打在小纹理图集中(如果纹理过大的话)
- 大量只有颜色差异的图片,避免重复纹理,可以采用分离变化区域贴图?
- UI背景贴图而不采用9宫格缩放的图,会使内存激增
- 纯色图没有使用Single Channel
- 不合理的半透明UI(粒子特效也要小心),占据大量屏幕区域,造成Overdraw开销
- 大量2D序列帧动画,而且图片大,还不打图集
- 不合理的通道图利用方案,多把通道利用上。
- 大量渐变色贴图,没有采用1像素过渡图,也不采用Single Channel, 粒子特效中较为常见。可以将贴图替换成曲线数据或采用单像素梯度纹理来减少内存开销和加载开销
优化成果
- 包体大小缩小了140MB左右
- Memory profiler 内存快照 纹理占用内存减少170MB左右
- profiler 真机运行情况,整体内存减少150MB左右
- profiler 真机运行情况,托管内存和显存也有成比例下降
- profiler 真机运行情况,纹理资源个数减少50个左右,内存大小减少170MB左右
Animation导入设置检查与优化
Rig标签页
Animation Type
类型 | 描述 |
---|---|
None | 无动画 |
Legacy | 旧版动画(unity3.0之前),不要用 |
Generic | 通用骨骼框架 |
Humanoid | 人形骨骼框架 |
选择原则:
- 无动画选择None
- 非人形动画选择Generic
- 人形动画
- 人形动画需要Kinematices或Animation Retargeting(动画重定向)功能,或者没有有自定义骨骼对象时选择Humanoid Rig
- 其他都选择Generic Rig,在骨骼数差不多的情况下,Generic Rig会比Humanoid Rig省30%甚至更多的CPU的时间。移动平台一般推荐这个,但骨骼数量要控制
Skin Weights
骨骼动画蒙皮顶点最多同时受几根骨骼的影响。默认4根骨头,但对于一些不重要的动画对象可以减少到1根,节省计算量(足球游戏观众台观众),Quality可以控制不同画质这个选项的大小
Optimize Bones
建议开启,在导入时自动剔除没有蒙皮顶点的骨骼
Optimize Game Objects
- 在Avatar和Animatior组件中删除导入游戏角色对象的变换层级结构,而使用Unity动画内部结构骨骼,消减骨骼transform带来的性能开销。可以提高角色动画性能
- 但有些情况下会造成角色动画错误,这个选项可以尝试开启但要看表现效果而定
- 注意如果你的角色是可以换装的,在导入时不要开启此选项,但在换装后在运行时在代码中通过调用AnimatorUtility.OptimizeTransformHierarchy接口仍然可以达到此选项效果
Animation标签页
Bake Animations
只有使用3dsmax、maya等dcc软件原始文件时且要有布料、流体等烘焙动画此选项才生效。FBX则禁用这个选项
Resmple Curves
将动画曲线重新采样为四元数数值,并为动画每帧生成一个新的四元数关键帧,仅当导入动画文件包含欧拉曲线时才会显示此选项
Anim.Compression
Unity动画无论压不压缩、重不重采样都会和dcc软件在表现上有所差异,取决于能不能看出来以及接受。
操作 | 描述 |
---|---|
Off | 不压缩,质量最高,内存消耗最大 |
Keyframe Reduction | 减少冗余关键帧,减小动画文件大小和内存大小 |
Keyframe Reduction and Compression | 减小关键帧的同时对关键帧存储数据进行压缩,只影响文件大小,内存和上一个选项一致 |
Optimal | 仅适用于Generic与Humanoide动画类型,Unity自动决定如何进行压缩(紧缩式和流式数据压缩) |
Rotation、Position、Scale Error
默认是0.5,表示transition在千分之五的自适应区间内两帧数据都可以看作一致,可以进行Keyframe Reduction,减少冗余关键帧。与unity单位有关,如果1000m的单位距离下,千分之五就是5m,5m内的transition都被看作是相同帧,可能会影响动画表现,需要手动调整该选项,压缩与表现要权衡
Animation Custom Properties
导入用户自定义属性,一般对应DCC工具中的extraUserProperties字段中定义的数据
动画曲线数据信息
动画优化时的重要数据
数据项 | 信息 |
---|---|
Curves Pos | 位置曲线 |
Quaternion | 四元数曲线 Resample Curves开启会有 |
Euler | 欧拉曲线 |
Scale | 缩放曲线 |
Muscles | 肌肉曲线,Humanoid类型下会有 |
Generic | 一般属性动画曲线,如颜色,材质等 |
PPtr | 精灵动画曲线,一般2D系统下会有 |
Curves Total | 曲线总数,数量越大性能越差 |
Constant | 优化为常数的曲线,error设置越大常数曲线越多,常数曲线一般不参与采样,越大说明优化程度越大 |
Dense | 使用了密集数据(线性插值后的离散值)存储 |
Stream | 使用了流式数据(插值的时间和切线数据)存储 |
动画文件导入设置优化后信息查看原则
- 看效果差异(与原始制作动画差异是否明显)
- 看曲线数量(总曲线数量与各种曲线数显,常量曲线比重大更好)
- 看动画文件大小(以移动平台为例,动画文件在小几百k或更少为合理,查过1M以上的动画文件考虑是否进行了合理优化)
其他资源导入与优化
TrueTypeFontImporter
支持TTF和OTF字体文件格式导入
- Rendering Mode:告诉unity使用字体渲染的哪种平滑模式
- 默认情况下使用smooth,是动态字体使用最快的模式
- Character:指定字符集
- Dynamic表示在运行时渲染字体字符集
- Custom Set可以在导入的字体中选择想要的字符
- Include Font Data 一般和动态字体配合使用
- 勾选后导入的字体文件会随app一起输出
- 如果是使用系统字不勾此选项可节省包体和内存
- Font Names:类似Fall CallBack,如果找不到对应字符会在这个列表的字体寻找
- References To Other Fonts In Project:选择项目内的其他字体作为后备字体
- 可以使用TMP工具和Custom Font创建自定义静态字体资源