乌啦呀哈呀哈乌啦!

欢迎光临,这里是喵pass的个人博客,希望有能帮到你的地方

0%

客户端性能优化

在面试中回答这个问题,建议从宏观的系统层面和微观的渲染层面两个维度来展开,并重点围绕“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 过于复杂),从而进行针对性的优化。