
移动优化技巧,针对技术艺术家 - 第一部分
您将从此页面获得: 为在Unity中工作的移动游戏开发者优化艺术素材的技巧。这是关于 优化移动游戏艺术的两篇文章 的第一篇。
您可以在 这本全面的电子书 和这个关于 移动应用程序的3D艺术优化的Unity Learn课程.

关注轮廓
在移动平台上,多边形和顶点的计算成本都很高。将多边形放置在真正有助于应用程序视觉质量的区域,以免浪费处理预算。
由于大多数移动设备的屏幕尺寸较小,以及您应用程序中3D对象的位置,3D对象上的许多小三角形细节可能不可见。这意味着您应该关注大型形状和有助于物体轮廓的部分,而不是可能不可见的小细节。使用纹理和法线贴图来获得细节。

使用细节级别 (LOD)
当物体远离时,细节层次 (LOD) 可以调整或切换它们以使用更简单的网格和更简单的材质和着色器,从而优化 GPU 性能。
更多 LOD 准备技巧
- 在较平坦的区域移除更多多边形,并且在低 LOD 的物体上不要使用密集的三角形区域。
- LOD 也可以应用于着色器复杂性。着色器和材质可以针对更远的 3D 物体进行优化。例如,您可以减少物体在远离相机时使用的纹理数量。
- 通常值得将每个 LOD 级别之间的三角形数量减少 50%。
- 检查不同距离下 LOD 的外观。
- 干净的拓扑对于变形或动画的角色和物体至关重要。
- 不要过于执着于完美的拓扑。一旦您应用了纹理和材质,玩家或最终用户将看不到 3D 模型的线框。
何时不使用 LOD
在每种情况下,LOD 并不适用。例如,避免在相机视图和物体都是静态的应用中使用它,或者物体已经使用低多边形计数的情况下。LOD 带来了内存开销和更大的文件大小,因为网格数据必须被保存以便实时使用。

合并网格并隐藏对象
您可以将多个网格合并为一个,以减少渲染所需的绘制调用数量。要应用此技术,请在层级中创建一个空的 GameObject,并使其成为您想要合并的网格的父级,然后将实现 Mesh.CombineMeshes() 方法的脚本附加到父级 GameObject 上。
使用遮挡剔除
隐藏在其他物体后面的物体仍然可能被渲染并消耗资源。使用遮挡剔除来丢弃它们。
虽然在相机视野外的视锥剔除是自动的,但遮挡剔除是一个预烘焙的过程。只需将您的物体标记为静态遮挡物或静态被遮挡物,然后通过窗口 > 渲染 > 遮挡剔除对话框进行烘焙。虽然并非每个场景都需要,但在许多情况下,剔除可以提高性能。查看使用遮挡剔除教程以获取更多信息。

导入模型
导入模型时,请记住以下一些好的提示。
- 动画类型:导入不包含任何动画数据的FBX网格时,在导入设置的Rig选项卡中将动画类型设置为无。当您将网格放入层级中时,此设置将确保Unity不会生成未使用的Animator组件。
- 禁用骨架和BlendShapes:如果您的网格不需要骨骼或BlendShape动画,请尽可能禁用这些选项。
- 禁用法线和切线:如果您绝对确定网格材质不需要法线或切线,请取消选中这些选项以节省额外的资源。
- 导入设置:如果您的模型在运行时没有被修改,请在导入设置的模型选项卡中禁用“启用读/写”选项,以防止在内存中创建副本。
- 静态/动态批处理:静态批处理是一种常见的优化技术,可以减少绘制调用的数量。它非常适合由大量顶点组成的对象,这些对象在渲染过程中不会移动、旋转或缩放。在包含目标模型的网格渲染器的检查器中检查静态。

纹理大小和颜色空间
纹理可以有不同的大小。减少需要较少细节的纹理的大小将有助于减少带宽。例如,漫反射纹理可以设置为1024 x 1024,相关的粗糙度/金属图可以设置为512 x 512。尽量选择性地减少纹理大小,并始终检查是否有任何视觉效果在之后被降级。
大多数纹理软件使用sRGB颜色空间处理和导出纹理。
我们建议您在sRGB颜色空间中使用漫反射纹理。未作为颜色处理的纹理不得在sRGB颜色空间中。这些纹理的例子包括金属、粗糙度和法线图,因为图是作为数据而不是颜色使用的。在这些图中使用sRGB将导致材料上的视觉效果错误。
注意:确保检查器窗口中的sRGB(颜色纹理)设置旁边没有粗糙度、镜面、法线图或类似项目的勾选。

将细节烘焙到纹理中
环境光遮蔽和小镜面高光等元素可以烘焙并添加到漫反射纹理中。这种方法意味着您不必过于依赖计算开销大的着色器和Unity功能来获得镜面高光和环境光遮蔽。

着色的灰度纹理
尽可能使用允许在着色器中进行颜色调 tint 的灰度纹理。这节省了纹理内存,但需要创建自定义着色器来执行调 tint。在使用此技术时要谨慎,因为并非所有对象都适合使用此方法。将此应用于具有均匀颜色的对象更容易。

纹理过滤
纹理过滤通常会改善场景中的纹理质量,但它也可能降低性能,因为实现更好的纹理质量通常需要更多的处理。纹理过滤有时可能占到 GPU 能耗的一半。选择更简单和更合适的纹理过滤器可以帮助减少应用程序的能量需求。
- 最近/点过滤:这是纹理过滤中最简单且计算强度最低的形式,尽管在近距离观察时,这种过滤可能会使纹理看起来块状。
- 双线性过滤:双线性过滤对相邻的纹理元素进行采样和平均,以为纹理中的像素上色。与最近过滤不同,双线性过滤产生的像素不那么块状,因为像素具有平滑的渐变。双线性过滤的一个副作用是,当近距离查看时,纹理会显得模糊。

纹理大小和颜色空间
您的大部分内存可能会用于纹理,因此这里的导入设置至关重要。一般来说,导入资产时请遵循这些指南。
- 降低最大尺寸:使用产生视觉上可接受结果的最低设置。这不会破坏原始数据,并且可以快速减少您的纹理内存。
- 使用二的幂 (POT):Unity 对于移动纹理压缩格式 (PVRCT 或 ETC) 要求使用 POT 纹理尺寸。
- 图集您的纹理:将多个纹理放入单个纹理中可以减少绘制调用并加快渲染速度。使用Unity Sprite Atlas或第三方TexturePacker来整理你的纹理。
- 关闭读取/写入启用选项:启用时,此选项会在CPU和GPU可寻址内存中创建副本,导致纹理的内存占用加倍。在大多数情况下,保持此选项禁用。如果你在运行时生成纹理,请通过Texture2D强制执行此操作。应用,传入makeNoLongerReadable 设置为true。
- 禁用不必要的mipmap:对于在屏幕上保持一致大小的纹理(如2D精灵和UI图形),不需要mipmap。对于与相机距离变化的3D模型,保持启用mipmap。
- 使用双线性过滤:这将有助于在性能和视觉质量之间取得平衡。
- 选择性使用三线性过滤:它比双线性过滤需要更多的内存带宽。
- 使用双线性和2倍各向异性过滤:选择这些而不是三线性和1倍各向异性,以改善外观和性能。
- 保持各向异性级别低:仅在关键游戏资产上使用高于2的级别。

压缩纹理
对iOS和安卓使用自适应可扩展纹理压缩(ATSC)。大多数正在开发的游戏倾向于针对支持ATSC压缩的最低规格设备。唯一的例外是:
- 针对A7设备或更低的iOS游戏(例如,iPhone 5、5S等):使用PVRTC
- 针对2016年之前设备的Android游戏:使用爱立信纹理压缩(ETC2)

使用纹理通道将多个纹理打包到一个纹理中
纹理通道打包有助于节省纹理内存,因为您可以将三个贴图放入一个纹理中。这意味着更少的纹理采样器。这种方法通常用于将粗糙度、光滑度和/或金属感打包到一个纹理中。它也可以应用于任何纹理遮罩。例如,您还可以存储alpha遮罩。具有透明度的图像可能会占用更大的内存,因为它们需要32位格式,但通过使用空闲通道存储alpha遮罩,您可以将漫反射纹理保持在16位,并有效地减小文件大小。
使用绿色通道存储最重要的遮罩。绿色通道通常有更多位,因为我们的眼睛对绿色更敏感,对蓝色的敏感度较低。

UV 展开
UV贴图将2D纹理投影到3D模型的表面上。UV展开是创建UV贴图的过程。
- 最佳实践是尽量保持UV岛,即展开纹理的单个单元,尽可能直,以便更容易打包UV岛并减少浪费空间。直的UV也有助于防止纹理上的阶梯效应。
- 在移动平台上,纹理空间是有限的。因此,纹理大小通常比控制台或PC小。良好的UV打包确保您从纹理中获得最高的分辨率。
- 考虑通过保持UV直线来稍微扭曲UV,以获得更高质量的纹理。
- 在某些情况下,您需要夸大和突出边缘和阴影,以改善形状可读性。由于移动平台通常使用较小的纹理,因此可能很难在那个小空间内捕捉到所需的所有细节。
- 对于移动应用程序,使用更少的纹理,并将任何额外细节烘焙到一个纹理中。这很重要,因为某些细节最好烘焙到漫反射纹理本身,以确保这些细节在小型移动屏幕上可见。