在面试中回答这个问题,建议从宏观的系统层面和微观的渲染层面两个维度来展开,并重点围绕“CPU瓶颈”与“GPU瓶颈”这两个核心概念来阐述。
系统层面
CPU与逻辑优化(解决主线程阻塞)
减少DrawCall(绘制调用)
- 这是最常见的优化点。通过静态合批(合并静态场景)、动态合批(合并同材质小模型)以及GPU Instancing(大量重复物体如草丛、子弹的实例化渲染)来大幅降低CPU向GPU发送指令的次数。
预加载
- 预加载常用的资源,比如场景中的静态资源、UI 资源、音效资源等等。
- 在场景加载阶段(Loading 界面)预先实例化核心 UI 并隐藏(SetActive(false)),这属于将提前初始化,而非延迟初始化,适合高频使用的核心界面。
异步处理与分帧加载 (Time-Slicing)
- 避免在每一帧(Update)中执行大量计算。将路径寻路、AI决策等耗时逻辑拆分到多帧执行,或者放入异步线程/WebWorker中,防止阻塞主线程导致卡顿。
- 对于包含大量子元素的列表(如背包系统),不要在同一帧初始化所有项。可以使用协程(Coroutine)每帧只初始化 2-3 个元素,避免单帧计算过载导致的掉帧。
物理与AI精简
- 关闭远处或视野外物体的物理碰撞检测和AI逻辑,只计算玩家周边的关键交互。
内存优化(杜绝泄漏与峰值溢出)
对象池
- 对象池可以提高对象创建和销毁的效率,因为对象池中的对象可以重复使用,从而避免了创建和销毁对象的开销。
- 延迟初始化后,不使用的 UI 不要直接 Destroy,而是放入对象池中。下次需要时,直接从池中取出并重新初始化,这比反复 Instantiate 性能更高。
延迟初始化
- 采用按需加载/Lazy Initialization的思路,在运行时加载需要的资源,而不是在编译时加载所有的资源。
- 仅在 UI 界面真正需要显示时,才调用 Instantiate 创建对象或从对象池中取出。
资源管理与按需加载
- 将资源采用高压缩率格式压缩,例如LZ4HC (用打包时间换空间)
- 大世界采用流式加载,只加载玩家周围一定范围内的资源;切换场景或退出副本时,强制卸载无用资源并释放内存。
网络与IO优化
协议压缩
- 使用 Protobuf 等二进制协议替代 JSON/XML,大幅减小数据包体积,解析速度更快。
- Protobuf 是基于预定义协议(契约),在“对象”和“二进制字节数组”之间进行高效、双向转换的通信标准
- Protobuf 按照提前写好的 .proto 协议文件(也就是双方约定好的“契约”),通过字段编号、数据类型等规则,进行极其精简的二进制编码。
数据差分同步
- 状态同步时只发送变化的数据(如位置偏移量、血量变化),而不是发送全量数据。
渲染层面
渲染优化的核心是减轻GPU的压力,核心指标是降低 Overdraw(过度绘制)和 FillRate(填充率)的消耗。
UI画布
动静分离
- 将频繁更新的动态 UI 与不常变动的静态 UI 拆分到不同的 Canvas 中,因为每次UI更新都会触发 Canvas 的重建。
- 这样当动态 UI 延迟加载并触发重建(Rebuild)时,不会影响到静态 Canvas 的性能。
降低 Overdraw(过度绘制)
- 控制透明层叠加:透明物体(如特效、粒子、UI流光)是 Overdraw 的重灾区。严格限制透明层的叠加数量(通常不超过2层),远距离的特效直接降低分辨率或关闭。
- 遮挡剔除(Occlusion Culling):开启引擎的遮挡剔除功能,被墙体等物体完全挡住的物体直接不参与渲染。
- 分层渲染:将UI、场景、角色、特效划分不同的渲染层级,透明与不透明物体严格分离。
避免 Layout Group 重建
- 瞬间加载大量元素到含有 VerticalLayoutGroup 的父物体时,会导致剧烈的 Layout 重建。
- 可以先禁用 Layout 组件,等所有元素加载完毕后,使用 LayoutRebuilder.ForceRebuildLayoutImmediate 一次性刷新。
模型与纹理优化
LOD(多细节层次)
- 根据物体距离摄像机的远近,自动切换不同精度的模型。远处的物体使用低模(面数少),近处使用高模。
纹理压缩与格式选择
- 使用 GPU 友好的压缩格式(如 ASTC、ETC2、BC7),在保证画质的前提下大幅降低显存占用和带宽压力。
Shader(着色器)轻量化
简化光照计算
- 移动端尽量避免复杂的光照模型、实时阴影和高光反射。
减少分支指令
- Fragment Shader(片元着色器)中的 if/else 分支会严重影响GPU并行计算效率,尽量用数学运算替代逻辑分支。
性能分析工具
- 优化不能靠猜,必须依赖工具。
- 常用的有 Unity 的 Profiler / Frame Debugger,或者第三方的 RenderDoc、Snapdragon Profiler。
- 通过这些工具可以精准定位到当前帧的瓶颈是在 CPU(如 DrawCall 过高)还是 GPU(如 Overdraw 严重或 Shader 过于复杂),从而进行针对性的优化。