UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - 简谱
type: channel
link: https://blog.uwa4d.com/tag/简谱/
items: Unity移动端游戏性能优化简谱之 功耗、发热和降频在软件层面的优化
items: Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（下）
items: Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）
items: Unity移动端游戏性能优化简谱之 达到GPU压力与画面表现间的平衡
items: Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（上）
items: Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）
items: Unity移动端游戏性能优化简谱之 前言

Unity移动端游戏性能优化简谱之 功耗、发热和降频在软件层面的优化
type: item
date: 2026-03-24T11:11:00+02:00
description: 《Unity移动端游戏性能优化简谱》共分为五个部分，今天向大家介绍文章的最后一部分：功耗、发热和降频在软件层面的优化，包含了移动端高功耗与发热产生机制、功耗与发热的定量数据分析、使用Perfetto的功耗调优实践等多项常见的游戏画面表现讲解。（全文长约3200字，预计阅读时间约15分钟） 前四部分可点击以下对应文章查看： 一、《Unity移动端游戏性能优化简谱之 前言》 二、《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）》 《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）》 三、《Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（上）》 《Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（下）》 四、《Unity移动端游戏性能优化简谱之 达到GPU压力与画面表现间的平衡》 1. 功耗、发热与降频基本原理 1.1 移动端高功耗与发热产生机制 手游运行时功耗由核心计算功耗（CPU/GPU/NPU）、访存功耗、外设功耗（屏幕/射频/传感器/存储）、系统调度开销四部分构成，其中对于手游来说尤其常见和需要关注的情况有： 高负载场景下（战斗、大世界渲染、物理模拟、网络同步），CPU/GPU持续高频运行，功耗可能持续过高； 手机机身散热面积有限，热量无法快速传导至外部，形成热堆积，且往往出现部分硬件模块压力尤其大，发热严重并传导到附近其他模块，使得这些模块也出现性能问题； 功耗与性能并非线性关系，超过能效拐点后，性能小幅提升会带来功耗大幅上涨，发热急剧恶化。 当SoC温度达到温控阈值，Android内核与固件会启动多级热防护机制，强制降低性能以控制发热，多数情况下体现为CPU/GPU频率降低、限制大核调度、减少并发线程数。 降频同时导致了CPU/GPU的算力下降，常直接导致游戏运行过程中帧率暴跌。尤其相对于其他前文讨论的性能问题，该问题反而在一些玩家的高端设备上更加显著，对于一些算力强劲的CPU/GPU，可能计算压力并不足以直接导致掉帧，但发热降频却导致了这些玩家有手机发烫、低帧卡顿等负面体验。 1.2 功耗与发热的定量数据分析 作为开发者和性能优化执行者，观察问题的视角显然还是要与玩家区分。因此，要精准定位功耗与发热的核心诱因，应避免依赖 “手感发烫”、“续航缩短”等主观感受，必须通过定量数据分析建立客观判断标准。正如上文讨论的，移动端游戏的功耗发热本质是硬件模块（CPU/GPU/存储/射频等）持续高负载运行的结果。所以定量分析的核心目标是：明确各硬件模块的功耗占比、定位高功耗场景的时间分布。 不过定量分析功耗发热问题的核心困难是，该问题其实已经脱离了游戏引擎可掌控的范畴，属于非常硬件层的问题。这就导致了不同芯片厂商、不同SoC厂商、不同手机厂商，其散热设计、保护机制等因素的不同都会导致发热和降频的情况互不相同；且他们提供的数据采集接口即便看起来单位一致，其实表示的实际开销也互不相同；在测试过程中，也会受到环境的干扰，比如冬夏气温、插电测试都会导致测试结果受到影响。 所以，应当尽量在固定设备使用可靠的工具进行测试，将数据进行按时间的、优化调试前后的纵向测试，而不是不同硬件、不同工具之间的横向测试。 1.3 使用Perfetto的功耗调优实践 1.3.1 市面上功耗测试工具评测 功耗优化的第一步是精准采集数据，市面上各类功耗测试工具各有优劣，需结合实际测试需求、设备适配性择优选用，以下是主流工具的实操测评与选型建议： （1）GOT Online作为常用性能监测工具，可实时采集帧率、帧耗时、CPU核心频率、内存占用、功耗峰值等核心数据，支持设备截屏、数据导出与对比分析，能直观呈现游戏运行时的功耗波动，基础监测能力在线，但针对细分硬件功耗的拆解能力有限。 （2）Trepn Profiler实测实用性较低，数据采集精度与稳定性难以满足专业调优需求；adb shell dumpsys batterystats指令虽能获取电池消耗数据，但数据维度单一、参考价值不大，仅能作为辅助参考，无法支撑深度功耗分析。 （3）Android Studio自带的Profiler工具，搭载On Device Power Rails Monitor（ODPM）模块，可监测CPU大小核、GPU、内存、屏幕、WiFi等硬件组件的功耗，但缺陷十分突出：不仅需要Debuggable包体，还仅适配Pixel系列机型，且测试时长不宜过长，通用性极差，难以适配主流安卓机型的规模化测试。 （4）Perfetto是移动端功耗测试的最优选择之一，无需Debuggable包体，支持USB/WebSocket连接实时录制。只不过在采集各硬件功耗轨道数据时，谷歌官方只在自己旗下的Pixel品牌手机中进行了专门的插桩，从…

Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（下）
type: item
date: 2026-03-24T04:54:00+02:00
description: 《Unity移动端游戏性能优化简谱》从Unity移动端游戏优化的一些基础讨论出发，例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题，并展示了如何使用UWA的性能检测工具确定和解决这些问题。内容包括了性能优化的基本逻辑、UWA性能检测工具和常见性能问题，希望能提供给Unity开发者更多高效的研发方法和实战经验。 今天向大家介绍文章第三部分：以引擎模块为划分的CPU耗时调优，共10小节，包含了渲染模块、UI模块、物理模块、动画模块、粒子系统、加载模块、逻辑代码、Lua等多个模块等常见的游戏CPU耗时调优讲解。 本章包含6-10小节，1-5小节请点击《Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（上）》。 （全文长约14115字，预计阅读时间约30分钟） 文章第一部分《Unity移动端游戏性能优化简谱之 前言》、第二部分《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）》、《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）》可戳此回顾，完整内容可前往UWA学堂查看。 6. 粒子系统 围绕粒子系统相关优化更全面的内容可以参考《粒子系统优化——如何优化你的技能特效》。 6.1 Playing粒子系统数量 UWA统计了粒子系统数量和Playing状态的粒子系统数量。前者是指内存中所有的ParticleSystem的总数量，包含正在播放的和处于缓存池中的；后者指的是正在播放的ParticleSystem组件的数量，这个包含了屏幕内和屏幕外的，我们建议在一帧中出现的数量峰值不超过50（1GB机型）。 针对这两个数值，我们一方面关注粒子系统数量峰值是否偏高，可选中某一峰值帧查看到底是哪些粒子系统缓存着、是否都合理、是否有过度缓存的现象；另一方面关注Playing数量峰值是否偏高，可选中某一峰值帧查看到底是哪些粒子系统在播放、是否都合理。 前文提到的控制同种粒子数量上限也是常见方案。 分级策略也是粒子系统优化过程中必不可少的手段。比如对于一个有12345，五种子粒子的火焰特效Prefab，其中345可能是美术同学用来做火焰燃烧时飞溅的火星、飘散的烟尘、空气的波动的，只有12是火焰本体。则低端机上应该考虑只保留12。 虽然我们在讨论粒子系统对耗时的影响时，多数时候还是在讨论粒子系统的渲染开销，无论是CPU端还是GPU端的。但对于粒子系统使用非常重度、数量非常多的项目来说，Playing的粒子过多也会对其本身在CPU端进行更新计算的ParticleSystem.Update()耗时有所影响。 6.2 Culling Mode 为粒子系统设置合理的Culling Mode也是一种有效降低粒子系统CPU端更新耗时的方式。 相关的关键设置为如上图的Simulation Space和Culling Mode。 其中，Simulation Space可选项有Local，World，Custom；CullingMode可选项为Automatic，Pause And Catch-up，Pause，Always Simulate。通常创建的粒子系统的默认选项是Local和Automatic。 我们显然希望当粒子在屏幕外看不到时停止相关运算、减少其耗时开销。因此我们测试在不同设置组合下粒子系统在屏幕外时的ParticleSystem.Update()函数耗时，结果如下： 在Local模式下，只有Culling Mode为Always Simulate有例子更新耗时（没有开启额外的Module）。 在Local模式下，如果粒子系统开启了Collision等Module，那么Culling Mode为Automatic时也会产生耗时。 在Local模式下，如果是Culling Mode为Pause或者Pause and Catch-up，就算有Collision Module也没有耗时。 在World模式下，Culling Mode为Automatic也会有耗时（没有开启额外的Module）。 在World模式下，Culling Mode为Pause，就算有Collision，也没有耗时。 综上，我们可以看到Culling Mode的设置对不同设置的粒子系统开销的限制能力是合理递进的，这说明我们在设置粒子系统时应尽量至少设为Automatic；应慎用Simulation Space为World的粒子；应慎用Collision、Trigger、Noise、Trails这些颇为常见的Module；对于确实要使用Module的粒子，也应考虑进一步调整设置为Pause等以节省耗时。 6.3 Prewarm ParticleSystem.Prewarm作为粒子系统的核心初始化选项，其设计初衷是为了…

Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）
type: item
date: 2026-03-20T12:10:00+02:00
description: 《Unity移动端游戏性能优化简谱》从Unity移动端游戏优化的一些基础讨论出发，例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题，并展示了如何使用UWA的性能检测工具确定和解决这些问题。内容包括了性能优化的基本逻辑、UWA性能检测工具和常见性能问题，希望能提供给Unity开发者更多高效的研发方法和实战经验。 今天向大家介绍文章第二部分：资源内存、Mono堆内存等常见游戏内存控制，共13小节，包含了纹理资源、网格资源、动画资源、音频资源、材质资源等多个资源内存以及Mono堆内存等常见的游戏内存控制讲解。 本章包含8-13小节，1-7小节请点击《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）》。 （全文长约11400字，预计阅读时间约20分钟） 文章第一部分《Unity移动端游戏性能优化简谱之 前言》可戳此回顾，完整内容可前往UWA学堂查看。 8. Render Texture 8.1 渲染分辨率 资源列表中的一些RT资源能反映项目当前的渲染分辨率。对于GPU和渲染模块压力较大的项目，在中低端机型上降低其渲染分辨率是非常直观有效的分级策略。但相关调整比起说影响内存，还是更多地影响GPU片元计算压力和带宽，后文GPU章节会进行更加详细的讨论。 如果一些其他的RT资源分辨率过高也应引起注意，尤其是2048*2048以上的资源。应当排查是否有必要用到如此精细的RT，在低端机上考虑采用更低分辨率的效果。 8.2 抗锯齿 资源列表中展示了RT资源的AA倍数。开启多倍AA会使RT占用内存成倍上升，并对GPU造成压力。建议排查是否有必要开启AA，尤其在中低端机上，可以考虑关闭此效果。 特别的是，在华为部分机型上2倍的AA会失效。即已经造成了性能消耗但没有实际起到抗锯齿效果。 8.3 后处理 一些常见的后处理相关的RT（如Bloom、Blur）是从1/2渲染分辨率开始采样，可以考虑改从1/4开始采样、并减少下采样次数，从而节省内存并降低后处理对渲染的压力。 站在性能优化的角度，在中低端机型上甚至最好分级地关闭各类后处理。围绕一些常见后处理效果的讨论会在下文GPU部分中进一步展开。 8.4 URP下的RT 使用URP时，内存中会多出_CameraColorTexture和_CameraDepthAttachment两份RT资源作为渲染目标，而开启URP相机的CopyDepth和CopyColor设置时会额外产生_CameraDepthTexture和_CameraOpaqueTexture作为中间RT。当资源列表中出现这两种RT时，需要排查确实是否用到CopyDepth和CopyColor，否则应予以关闭以避免不必要的浪费。 9. Shader资源 9.1 ShaderLab Unity 2019.4.20是Shader内存统计方法的一个转折点。在此之前，Shader的内存主要统计在ShaderLab中，而之后则主要统计在Shader资源自身身上。 对于Unity 2019.4.20之前的版本的项目，查看ShaderLab的内存使用Memory Profiler截帧查看。而无论是Shader资源本体还是ShaderLab内存占用过高，都要着手于控制Shader的数量、变体数量和Shader复杂度。 9.2 变体数和复杂度 对于单个Shader资源而言，其内存占用高本质在于其编译后的行数高。因此也可以视为，怎么控制变体的数量和每个变体的平均行数（也就是Shader的复杂度），这两个乘数的问题。 其中，变体数过多是造成一个Shader资源内存占用过大、占用包体过大的主要原因，也是相对比较好和排查和修改的部分。在项目迭代中可能会出现已经被弃用或者没有被实际使用到的关键字，导致变体成倍上升；又或者Shader写的比较复杂，其中一些关键字组合永远不会被用到，从而导致很多变体是多余的。UWA的本地资源检测中提供了Shader检测功能，可以看到变体数量，定位变体数过多的Shader资源。 针对上述情况，Unity提供了回调函数，在项目打AssetBundle包或者Build时线剔除用不到的关键字或关键字组合相关的变体。剔除Shader变体的方法可以参考《Stripping scriptable shader variants》。 而Shader的复杂度同时还涉及到GPU性能相关的优化。具体在后文GPU部分有更加详细的讨论。 9.3 冗余 Shader冗余尤其需要予以关注，Shader的冗余不光导致内存上升，还可能造成重复解析，即运行时不必要的Shader.Parse和Shader.CreateGPUProgram API调用耗时。 一般的做法是，首先使用ShaderVariantCollection这一Unity…

Unity移动端游戏性能优化简谱之 达到GPU压力与画面表现间的平衡
type: item
date: 2022-06-28T10:21:00+03:00
description: 《Unity移动端游戏性能优化简谱》共分为五个部分，今天向大家介绍文章的第四部分：达到GPU压力与画面表现间的平衡，共7小节，包含了GPU Clocks与GPU Bound、GPU顶点阶段计算压力、GPU片元阶段计算压力、着色器复杂度、后处理、带宽等多项常见的游戏画面表现讲解。（全文长约4400字，预计阅读时间约15分钟） 前三部分可点击以下对应文章查看： 一、《Unity移动端游戏性能优化简谱之 前言》 二、《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）》 《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）》 三、《Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（上）》 《Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（下）》 1. 总览 近几年中，市场上部分画面质量很高的成功项目正逐渐使得行业变得更“卷”，甚至一定程度上跨越了游戏类型和赛道的限制，让更多开发者发现优质的画面和诱人的玩法一样，成为吸引和留住玩家不可或缺的重要手段。伴随着这种倾向，许多团队在开发过程中把大量重心倾斜到了美工制作和渲染效果的实现上。但随之而来就产生了很多问题：渲染压力越来越高，尤其是很多开发者对配套的渲染性能监控和维护不够了解，产生了很多低效的流程甚至后期弥补造成的大量成本。 而其中，GPU端更是已经超越了CPU端，成了许多项目性能压力的最主要来源之一。但GPU端往往更多地涉及到硬件层面的问题，市面上不同的厂商不同的芯片会反应出不同的现象，为开发者进行机型分档和标准制定造成了困扰。从另一个角度来说，针对GPU性能的检测往往不是Unity引擎相关的工具所能提供的，而硬件厂商提供的各类工具则繁多而难用，看得人眼花缭乱而抓不住重点，实质上为GPU性能问题的排查和优化带来了巨大的困难。那么，我们有没有一个相对具有共性和普遍性的思路或方法论，来判断一个项目是否有GPU压力——如果有，是什么类型的压力、又分别该如何处理呢？ 基于市面上这类工具的缺位和日益迫切的GPU性能优化的需求，UWA在2023年下半年开始推出了GOT Online全新的第五大模式：专注GPU性能的GPU模式，力求做到一个工具兼容市面上所有移动端硬件厂商的设备，并且给出对实际优化工作具有现实指导意义的参数。 但在讨论GPU模式如何处理分析GPU性能问题之前，我们不妨先回顾一下移动端游戏每一帧渲染的流程。CPU负责应用阶段，GPU则负责后续的几何阶段和光栅阶段。对于多数开启多线程渲染的项目而言，主线程中的渲染模块CPU端主函数主要处理DrawCall的准备、Culling计算等工作，而同时开辟了渲染线程，将同样非常耗性能的向GPU提交纹理、向GPU提交DrawCall、等待GPU完成工作的工作全部交由渲染线程进行。一般对于渲染压力较大的场景，当你注意观察此时的Timeline时，可能会发现如下图所示的现象：主线程必须等待渲染线程完成上一帧的工作才能开始这一帧渲染模块的工作，而此时渲染模块中主要在进行DrawCall的提交和等待GPU完成上一帧的工作。 此处，主线程中的Gfx.WaitForPresentOnGfxThread即为等待渲染线程完成工作的标记，而渲染线程中的Gfx.PresentFrame则代表了等待GPU完成工作的标记。它们本身不代表实际的耗时开销，而仅仅是多线程渲染和CPU-GPU同步等待机制下的性能标记。 图中的性能情况即为非常典型的GPU Bound。此时CPU压力不大，各个模块的耗时总和小于目标30帧率所需的33ms，但GPU压力却使得游戏此时仅能跑十几帧，而此时对CPU作常规的优化将并无任何效果。比如你这一帧中CPU耗时为30ms，总计实际要等待GPU 80ms，你此时的同步等待标记显示为50ms，而你现在将CPU耗时大幅优化至20ms，你的帧率不会有所上升，因为此时同步等待标记要花80-20=60ms了。当然，反过来说，当一个项目的CPU耗时有80ms，此时完全检测不到等待标记耗时，但并不是就说一定就没有GPU压力了——而可能只是被CPU高压掩盖了。 就是这样一个简单的木桶效应，而它开始在近几年中大量地出现在UWA遇到的各种移动端项目中，这也是为什么上文有“GPU端更是已经超越了CPU端，成了许多项目性能压力的最主要来源”这一说法。 那么，到这里为止，我们似乎已经足以判断项目在当前测试设备和分档上的测试流程中是否存在GPU压力。但Gfx.WaitForPresentOnGfxThread本身到底只是一个没有实际耗时意义的同步等待标记，也会如上文提到的一样受CPU压力等影响，并不总是能够准确地标定究竟哪些场景哪些画面的GPU压力更大，更不用说它无法指导我们作具体的GPU性能优化和分级。 那…

Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（上）
type: item
date: 2022-06-20T05:19:00+03:00
description: 《Unity移动端游戏性能优化简谱》从Unity移动端游戏优化的一些基础讨论出发，例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题，并展示了如何使用UWA的性能检测工具确定和解决这些问题。内容包括了性能优化的基本逻辑、UWA性能检测工具和常见性能问题，希望能提供给Unity开发者更多高效的研发方法和实战经验。 今天向大家介绍文章第三部分：以引擎模块为划分的CPU耗时调优，共10小节，包含了渲染模块、UI模块、物理模块、动画模块、粒子系统、加载模块、逻辑代码、Lua等多个模块等常见的游戏CPU耗时调优讲解。 本章包含1-5小节，6-10小节请点击《Unity移动端游戏性能优化简谱之 以模块思维划分的CPU耗时调优（下）》。 （全文长约14115字，预计阅读时间约30分钟） 文章第一部分《Unity移动端游戏性能优化简谱之 前言》、第二部分《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）》、《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）》可戳此回顾，完整内容可前往UWA学堂查看。 1. 总览 1.1 模块划分 UWA将CPU中工作内容明确、耗时占比一般较高的函数整理划分为：渲染、UI、物理、动画、粒子、加载、逻辑等模块。但这并不意味着模块之间的工作互相独立毫无关联。举例而言，渲染模块的性能压力势必受到复杂的UI和粒子影响，而加载模块的很多操作实际上都是在逻辑中调用并完成的。 划分模块有利于我们确认问题、找到重点。与此同时，也要建立起模块之间的关联，有助于更高效地解决问题。 1.2 耗时瓶颈 当一个项目由于CPU端性能瓶颈而产生帧率偏低、卡顿明显的现象时，如何提炼出哪个模块的哪个问题是造成性能瓶颈的主要问题就成了关键。尽管我们已经对引擎中主要模块做了整理，各个模块间会出现的问题还是会千奇百怪不可一以概之，而且它们对CPU性能压力的贡献也不尽相同。那么我们就需要对什么样的耗时可以认为是潜在的性能瓶颈有准确的认知。 在移动端项目中，我们CPU端性能优化的目标是能够在中低端机型上大部分时间跑满30帧的流畅游戏过程。为了达成这一目标，简单做一下除法就得到我们的CPU耗时均值应控制在33ms以下。当然，这并不意味着CPU均值已经在33ms以下的项目就已经把CPU耗时控制的很好了。游戏运行过程中性能压力点是不同的，可能一系列UI界面中压力很小、但反过来游戏中最重要的战斗场景中帧率很低、又或者是存在大量几百毫秒甚至几秒的卡顿，而最终平均下来仍然低于33ms。 为此，UWA认为，在一次测试中，当33ms及以上耗时的帧数占总帧数的10%以下时，可以认为项目CPU性能整体控制在正常范围内。而这个占比越高，说明当前项目的CPU性能瓶颈越严重。 以上的讨论内容主要是围绕着我们对CPU性能的宏观的优化目标，和内存一样，我们仍要结合具体模块的具体数据来排查和解决项目中实际存在的问题。 2. 渲染模块 围绕渲染模块相关优化更全面的内容可以参考《Unity性能优化系列—渲染模块》。 2.1 多线程渲染 一般情况下，在单线程渲染的流程中，在游戏每一帧运行过程中，主线程（CPU1）先执行Update，在这里做大量的逻辑更新，例如游戏AI、碰撞检测和动画更新等；然后执行Render，在这里做渲染相关的指令调用。在渲染时，主线程需要调用图形API更新渲染状态，例如设置Shader、纹理、矩阵和Alpha融合等，然后再执行DrawCall，所有的这些图形API调用都是与驱动层交互的，而驱动层维护着所有的渲染状态，这些API的调用有可能会触发驱动层的渲染状态地改变，从而发生卡顿。由于驱动层的状态对于上层调用是透明的，因此卡顿是否会发生以及卡顿发生的时间长短对于API的调用者（CPU1）来说都是未知的。而此时其它CPU有可能处于空闲等待的状态，从而造成浪费。因此可以将渲染部分抽离出来，放到其它的CPU中，形成单独的渲染线程，与逻辑线程同时进行，以减少主线程卡顿。 其大致的实现流程是，在主线程中调用的图形API被封装成命令，提交到渲染队列，这样就可以节省在主线程中调用图形API的开销，从而提高帧率；渲染线程从渲染队列获取渲染指令并执行调用图形API与驱动层交互，这部分交互耗时从主线程转到渲染线程。 而Unity在Project Settings中支持且默认开启了Multithreaded Rendering，一般建议保持开启。在UWA的大量测试数据中，还是发现有部分项目关闭了多线程渲染。开启多线程渲染时，CPU等待GPU完成工作的耗时会被统计到Gfx.WaitForPresent函数中，而关闭多线程渲染时这一部分耗时则被主要统计到Graphics.PresentAndSync中。所以，项目中是否统计到Gfx.W…

Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（上）
type: item
date: 2022-06-10T09:10:00+03:00
description: 《Unity移动端游戏性能优化简谱》从Unity移动端游戏优化的一些基础讨论出发，例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题，并展示了如何使用UWA的性能检测工具确定和解决这些问题。内容包括了性能优化的基本逻辑、UWA性能检测工具和常见性能问题，希望能提供给Unity开发者更多高效的研发方法和实战经验。 今天向大家介绍文章第二部分：资源内存、Mono堆内存等常见游戏内存控制，共13小节，包含了纹理资源、网格资源、动画资源、音频资源、材质资源等多个资源内存以及Mono堆内存等常见的游戏内存控制讲解。 本章包含1-7小节，8-13小节请点击《Unity移动端游戏性能优化简谱之 分门别类地控制运行时内存（下）》。 （全文长约11400字，预计阅读时间约20分钟） 文章第一部分《Unity移动端游戏性能优化简谱之 前言》可戳此回顾，完整内容可前往UWA学堂查看。 1. 总览 1.1 运行时内存占用 首先，在讨论内存相关的各项参数和制定标准之前，我们需要先理清在各种性能工具的统计数据中常出现的各种内存参数的实际含义。 在包括UWA在内的多种性能工具中，我们最常见到和关心的PSS（Proportional Set Size）Total内存，其含义为一个进程在RAM中实际使用的空间地址大小，即实际使用的物理内存（比例分配共享库占用的内存，按照进程数等比例划分），也即我们游戏进程的实际运行时内存占用。 不过，有的时候也会出现使用RSS Total参数的工具。它和PSS同样代表实际使用的物理内存，不过包含了共享库占用的全部内存，有时会偏大，参考性相对下降；而共享库内存是不会导致杀进程的。在下文它出现的时候，会额外标记。 当然，在实践过程中这两个值还会受到安卓系统版本、具体硬件机型等因素的影响。 无论如何，游戏运行过程中闪退，或暂时切出（如玩家游戏过程中切到社交软件回复信息）就被杀进程，对玩家体验显然是一种严重的破坏。而在UWA经验中，上述两个现象绝大多数情况下都是过高的运行时内存导致的。 当系统内存触发高占用告警时，系统会根据进程优先级自动终止部分进程以释放内存。这也是许多开发者在闪退日志中看到的Out of Memory（OOM）类型闪退的主要原因。 在系统的进程优先级体系中，包括游戏进程在内的玩家应用通常处于较低的一档；而在同一优先级层级中，内存占用越高的进程，被系统终止的概率也越大。因此，游戏进程往往成为被系统杀死的高风险对象。 由于我们几乎无法在引擎层面对系统进程优先级进行重新调度或调整，因此在实际项目中，控制PSS Total的整体占用，仍然是最常见且最有效的优化手段。 有了这样一个总值，当我们发现总值过高时，就需要予以拆解才能定位到问题。接下来，我们从两个视角来拆解PSS Total： 首先是很多开发者都有在用、相对熟悉的Memory Profiler。该工具对内存的划分和命名也一直在随版本调整，因此本文就比较常用的Memory Profiler 0.7.1和1.1.0版本进行分析，在笔者看来，两者各有千秋，实际使用时甚至经常两个一起用。以下是同一个Snapshot结果在两个不同版本上的解析结果： 0.7.1 老版的Summary界面把内存以三个维度进行拆分，比较清晰。其中还能看到In use和Reserved部分分别占了多少，体现出了预留内存。 但老版的细节分析页整合地较差，甚至Take Example时都能清晰呈现的Manager、SerializedFile等类型都没有区分出来。且还需要自己点击分类、隐藏不需要的字段、按大小排序，才能看到上图这样相对有价值的画面。 1.1.0 新版的Summary将原本最上层相对价值较低的维度删除，反之对五种资源内存做了拆分。但主要问题在于移除了预留值的呈现，全部（甚至包括堆内存的预留值）都被计入了Native。 新版的细节整合页明显要好的多，分类更全面清晰，且已经做好了排序、还有简单的可视化。但上面提到的预留值，包括IL2CPP虚拟机的内存都被算进了Unknown里。在UWA的一些排查经验中，还发现会有个别特殊情况会导致这里的Unknown特别高，比如项目的AssetBundle使用LZMA格式进行打包时。尽管知道是不怎么需要针对性优化的部分，但看到这几百MB的占用总还是比较糟心的；更别说很多开发者不理解这部分占用时产生的困惑了。所以，有时候两个版本都看一下作对比就能发现问题。 接下来我们还是取0.7.1的Summary进行详细介绍。可以看到，在图中的第一部分，Unity把统计到的运行时内存总值（此处Unity抓取了RSS内存）分成了两大部分：Tracked Memory和Untracked Memory。 Tracked Memory为Unity引擎分配的…

Unity移动端游戏性能优化简谱之 前言
type: item
date: 2022-06-08T08:28:00+03:00
description: 《Unity移动端游戏性能优化简谱》是从Unity移动端游戏优化的一些基础讨论出发，例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题，并展示了如何使用UWA的性能检测工具确定和解决这些问题。内容包括了性能优化的基本逻辑、UWA性能检测工具和常见性能问题，希望能提供给Unity开发者更多高效的研发方法和实战经验。 今天向大家介绍第一部分，共五小节。完整内容请前往UWA学堂查看。 玩家眼中的游戏性能 开发者关注的游戏性能 如何确定问题 如何解决问题 如何持续监控性能 前言 1. 玩家眼中的游戏性能 任何一个玩家在游玩游戏过程中都会碰到类似的疑问：为什么我玩一段时间就会闪退？为什么我的游戏这么卡？为什么我的硬件这么烫？为什么移动设备电量下得这么快？ 对于玩家而言，无关手里这款游戏本身的美术是否精良、玩法是否有趣，当上述这些疑问出现时，其游戏体验会自然而然地变差，并不可避免地导致黏性下降。这是每个游戏开发者都不想看到的结果。 而实情是，对于如今的移动端游戏市场而言，国内市面上各类硬件机型性能跨度很大；如果项目要支持海外市场，则往往项目所要承担的性能压力更大。那么，如何让持有不同硬件设备的玩家，尤其是通过中低端设备接触到我们游戏项目的玩家也能顺利流畅地体验游戏内容，就是我们今天讨论的主要话题。 2. 开发者关注的游戏性能 在游戏项目的开发过程中，一个非常常见的现象是：研发团队在新项目的中前期往往把全部精力投入到实现功能中去，而忽略了性能优化的工作；到了游戏中后期甚至临近上线的时候进行测试，才发现项目充斥着大量严重的性能问题、影响到了游戏的正常体验，但却不知道从何改起、时间非常窘迫；再到上线后，受到大量玩家对性能的负面反馈，留存数据也受到影响。 足以见得，性能问题是一款游戏项目重要的生命线，需要开发者树立良好的优化意识和优化知识体系，才能让项目少走弯路。 和玩家视角不同的是，像闪退、卡顿、发热、耗电这种感官层面的性能问题，UWA认为在开发者的视角中应该将其主要分类为内存、CPU、GPU三个大类的问题。本文的主要内容旨在围绕三个大类的常见典型问题进行例举和讨论，从而形成一份Unity移动端游戏性能优化方法论的简谱。 那么，既然已经发现了若干性能问题，如何排查确定问题和解决问题就成了最关键的两个步骤。 3. 如何确定问题 发现了性能问题后的第一大步骤就是确定问题。 举例而言，我们的游戏项目运行时间一长就会闪退，是因为我们的缓存策略做的不好或者存在冗余现象，导致内存不断上升造成的闪退？还是因为我们的美术资源内存控制的不好，几个较大的资源就轻易把整体内存给撑大了？ 又或者我们发现一个游戏场景卡顿严重、帧率很低，是因为这里的同屏渲染面片数和DrawCall数都太高导致渲染模块压力大？还是因为此处的UI过于复杂且变化频繁造成的更新耗时？ 还或者我们感到手里的手机烫的惊人，是不是因为当前场景GPU压力过大，我们在当前机型上做的分级策略并不合适？ 以上只是众多千奇百怪层出不穷的性能问题中的寥寥几点。后文还将详细讨论一些比较常见的问题。总之，确定问题的工作本身也是一项挑战。 3.1 计算机语言/图形学/游戏引擎知识 知识和经验无疑是一个开发者在优化项目性能时最宝贵的武器，不断地学习和更新也是每一个程序员武装起自己的过程。完善而饱满的知识自然不仅仅有利于确定问题，同样有助于解决问题。放在这里说是因为它是我们有能力着手优化工作的重要前提。 除了查看各类工具源码和文档、跟踪工具更新内容、翻阅大牛撰写的书籍、浏览各类技术论坛和博客等等以外，也可以在UWA的技术社区中找到很多优质内容。 UWA 学堂：持续更新各类优质课程，内容从某些开发工具的入门和使用到某个引擎模块的机制原理详解；从最新的移动端游戏技术实践到精品项目案例讲解等等。还邀请了众多具有多年从业经验的业界大佬和著名游戏公司合作伙伴撰稿，涵盖面广、质量颇高。更有每年侑虎科技UWA主办的UWA DAY游戏开发者大会的优秀内容。 UWA问答：帮助开发者找到更好的答案。是游戏开发者们日常沟通交流技术问题的良好平台。在这里你对游戏制作方方面面的任何问题，都能够得到讨论或解答。通过最直接的技术交流来少走弯路、获得经过实践检验的开发经验，让确定和解决问题的过程变得简单许多。 UWA开源库：帮助开发者发现更好的解决方案。不断更新和整合了各种来源的开源项目，翻译完毕、分类清晰、图文并茂，为开发者提供了更加方便地搜索发现和获取开源资源的渠道。 UWA Blog：包含UWA精选的各类技术文章、提醒学堂优质内容上新、整合问答优质问题、介绍UWA产品和其更新等各类UWA社区动向。 3.2 多种多样的辅助工具 工欲善其事必先利其器。使用工具获得直接精确的性能数据，能更加直观地反映出性能瓶颈，从而达到事半功倍…