公司动态
CPU 优化:物理与动画——两个“偷偷吃 CPU“的大户
开场一个逻辑没多少却卡爆 CPU的谜团小王的游戏逻辑很简单可 Profiler 一看 CPU——Physics 和 Animation 两块红得发紫“我游戏逻辑就那么点怎么 CPU 全耗在物理和动画上了一堆刚体、一堆碰撞、几十个动画角色……这两块到底怎么优化有哪些坑”老鸟说“物理和动画是 CPU 优化的两座大山物理靠’碰撞检测、刚体模拟’吃 CPU动画靠’骨骼计算、曲线采样’吃 CPU它俩优化得好CPU 能省一大截今天把这两块掰开讲透”第一部分物理优化 第一幕物理为什么吃 CPU物理引擎在忙什么物理引擎每帧要做 ① 碰撞检测:谁和谁撞了? ② 刚体模拟:算速度、受力、位置 ③ 约束求解:关节、堆叠等 ↓ 物体越多、碰撞越复杂 → 计算量爆炸增长!碰撞检测的开销核心碰撞检测 物理开销大头 N个物体两两检测 → 接近N²增长! 100个物体 → 可能上千次检测 ↓ 所以物理优化核心之一: 减少碰撞检测的量和复杂度!生动理解物理开销物理模拟像裁判盯着一群人防碰撞 场上人越多(物体多) 裁判越要拼命盯谁会撞谁(碰撞检测) 还要算撞了怎么弹开(刚体模拟) ↓ 人一多,裁判累到崩溃(CPU爆)! 第二幕物理优化核心手段⭐手段1优化碰撞体形状碰撞体复杂度(从便宜到贵) Sphere(球) Capsule(胶囊) Box(盒) Mesh Collider(网格)! ↓ ✅ 优化 - 尽量用简单碰撞体(球/胶囊/盒) - 避免Mesh Collider(超贵!) - 用几个简单碰撞体拼,别用网格碰撞手段2Mesh Collider 用凸包必须用Mesh Collider时 ✅ 勾选Convex(凸包) → 简化成凸多面体,便宜很多 ↓ ⚠️ 非凸(Concave)网格碰撞超贵 且不能做动态刚体!手段3用好碰撞矩阵(Layer)⭐Layer Collision Matrix(层碰撞矩阵) 设置哪些层之间需要检测碰撞 ↓ ✅ 关闭不需要的层之间的碰撞: - 子弹层 vs 子弹层 → 关(子弹不互撞) - 特效层 vs 任何层 → 关 ↓ Edit Project Settings Physics → 取消勾选不需要的交叉! ↓ 大幅减少无谓的碰撞检测!手段4静态物体标记正确✅ 不动的碰撞体: - 不要加Rigidbody(保持静态) - 静态碰撞体物理引擎有优化 ↓ ⚠️ 千万别给静态碰撞体的 Transform频繁移动! → 会导致物理引擎重建,超贵!生动理解物理优化物理优化像给裁判减负 ① 简单碰撞体 → 让裁判判简单形状(快) ② 层矩阵 → 告诉裁判这些人不用管 ③ 静态标记 → 这些人不动,别老盯着 ↓ 裁判轻松 → CPU省! 第三幕物理的高级优化优化1降低 Fixed Timestep物理在FixedUpdate运行,固定频率 默认Fixed Timestep 0.02(每秒50次) ↓ ✅ 如果物理精度要求不高: 调大到0.03~0.04(每秒25~33次) → 物理计算次数减少! ↓ ⚠️ 别太大,否则物理不稳定/穿透 Edit Project Settings Time优化2Rigidbody 休眠Rigidbody静止后会自动休眠(Sleep) → 休眠的刚体不参与模拟(省CPU) ↓ ✅ 别做打断休眠的事: - 别每帧对静止刚体施加微力 - Sleep Threshold可调 ↓ 让静止物体好好睡觉!优化3减少物理查询物理查询(Raycast/OverlapSphere等)也耗CPU ✅ 优化 - 别每帧大量Raycast - 用LayerMask限定检测层(减少检测量) - 降低查询频率(不用每帧查) - RaycastNonAlloc避免GC// ✅ 用LayerMask NonAllocRaycastHit[]resultsnewRaycastHit[10];intcountPhysics.RaycastNonAlloc(ray,results,maxDist,layerMask);// ↑ 限定层 不产生GC优化4碰撞事件按需用⚠️ OnCollisionStay/OnTriggerStay每帧调用! 物体多时开销大 ↓ ✅ 优先用Enter/Exit Stay能不用就不用生动理解高级优化高级优化像进一步精简裁判工作 ① 降低判罚频率(Fixed Timestep) ② 让不动的人休息(休眠) ③ 少发起主动检查(少Raycast) ④ 少用持续性监控(少Stay) ↓ 裁判工作量再降一档!第二部分动画优化 第四幕动画为什么吃 CPU动画在忙什么动画每帧要做 ① 采样动画曲线(算每根骨骼的位置/旋转) ② 混合多个动画(Blend) ③ 更新骨骼矩阵 ④ 蒙皮计算(骨骼影响顶点) ↓ 骨骼越多、角色越多 → 计算量越大!Animator 的隐藏开销⚠️ Animator(Mecanim)比较重 - 状态机评估 - 即使角色没动,也在跑评估! ↓ 大量角色用Animator → CPU吃紧生动理解动画开销动画像提线木偶师操控木偶 每个木偶(角色)有很多线(骨骼) 木偶师每帧要拉动所有线(采样) 还要平滑过渡动作(混合) ↓ 木偶越多、线越多 → 木偶师累爆(CPU)! 第五幕动画优化核心手段⭐手段1剔除看不见的动画⭐✅ Animator的Culling Mode: 设为Cull Completely或 Cull Update Transforms ↓ 角色不可见时: → 不更新动画(省CPU!) ↓ 在Animator组件设置Culling Mode!Culling Mode选项: - Always Animate: 总是更新(最贵) - Cull Update Transforms: 不可见时不更新Transform - Cull Completely: 不可见时完全停止(最省)手段2降低动画更新频率(LOD)✅ Animator LOD / 远处降频 远处的角色: → 降低动画更新频率 → 或用更简单的动画 ↓ 远处角色动画糙点没人看得出!手段3减少骨骼数量✅ 角色骨骼优化 - 远处/次要角色用少骨骼模型 - Quality Settings的Blend Weights (每顶点受几根骨骼影响)调低 ↓ 骨骼少 → 计算少!手段4大量角色用 GPU 方案✅ 超大量角色(人群): - 用GPU Instancing 顶点动画(VAT) - 把动画烘焙到纹理,GPU播放 → 绕开CPU的骨骼计算! ↓ 万人同屏的方案!生动理解动画优化动画优化像给木偶师减负 ① 看不见的木偶不操控(剔除)⭐ ② 远处木偶随便动动(降频/LOD) ③ 减少每个木偶的线(减骨骼) ④ 大量木偶改用机器批量(GPU) ↓ 木偶师轻松 → CPU省! 第六幕动画的进阶优化优化1Optimize Game Objects✅ 模型导入设置: Rig Optimize Game Objects ↓ 把骨骼Transform层级优化掉 → 减少Transform开销 ↓ ⚠️ 优化后骨骼不在Hierarchy 要访问特定骨骼需Extra Transforms暴露优化2Animator vs 简单动画⚠️ 简单动画别用重量级Animator 简单的开关门、UI动画: → 用Animation组件(轻) 或DOTween等补间(更轻) 或直接代码控制 ↓ Animator适合复杂状态机 简单动画杀鸡别用牛刀!优化3避免每帧改 Animator 参数// ❌ 坏:每帧设置(即使没变)voidUpdate(){animator.SetFloat(Speed,speed);// 每帧!}// ✅ 好:变了才设置voidUpdate(){if(speed!lastSpeed){animator.SetFloat(Speed,speed);lastSpeedspeed;}}⚠️ 用Hash代替字符串参数名: int speedHash Animator.StringToHash(Speed); animator.SetFloat(speedHash, speed); → 避免字符串查找开销优化4控制 Animator 数量✅ 场景里的Animator: - 不需要的角色禁用Animator - 用对象池管理(复用) - 远处/静止的可禁用 ↓ Animator数量直接影响CPU!生动理解进阶优化进阶优化像精细化管理木偶师 ① 简化木偶结构(Optimize GameObjects) ② 简单动作别请大师(别滥用Animator) ③ 没变化别瞎指挥(参数按需设Hash) ④ 控制木偶数量(管理Animator) ↓ 方方面面省CPU! 第七幕物理与动画优化对照总结物理优化清单✅ 物理优化 □ 用简单碰撞体(球/胶囊/盒) □ 避免Mesh Collider(用就勾Convex) □ 配置Layer碰撞矩阵(关无用碰撞)⭐ □ 静态物体不加Rigidbody □ 别移动静态碰撞体 □ 调整Fixed Timestep □ 利用Rigidbody休眠 □ 减少Raycast用LayerMaskNonAlloc □ 少用OnCollisionStay/TriggerStay动画优化清单✅ 动画优化 □ 设置Culling Mode剔除不可见⭐ □ 远处角色动画降频/LOD □ 减少骨骼数量 □ 大量角色用GPU方案(VAT) □ Optimize Game Objects □ 简单动画别用Animator □ 参数按需设置用Hash □ 控制Animator数量 第八幕如何定位物理/动画瓶颈用 Profiler 定位✅ Unity Profiler - Physics模块: 看物理开销 - 找Physics.Processing等耗时 - CPU模块看Animators.Update耗时 ↓ 看清是物理还是动画的锅!关键指标物理: 看Physics.Simulate、碰撞检测耗时 看物理查询(Raycast)数量 动画: 看Animator.Update耗时 看有多少Animator在跑 ↓ 定位到具体开销源!✅ 物理与动画优化检查清单物理理解 □ 明白物理靠碰撞检测刚体模拟吃CPU □ 明白物体越多碰撞越贵(接近N²) 物理优化 □ 会用简单碰撞体 □ 会配置Layer碰撞矩阵⭐ □ 会调Fixed Timestep □ 会优化Raycast(LayerMaskNonAlloc) 动画理解 □ 明白动画靠骨骼采样混合吃CPU □ 明白Animator即使不动也有开销 动画优化 □ 会设Culling Mode剔除不可见⭐ □ 会远处降频/LOD □ 知道大量角色用GPU方案 □ 会参数按需设置用Hash 定位 □ 会用Profiler分辨物理/动画瓶颈 一句话总结CPU 优化之物理与动画【物理】靠碰撞检测 刚体模拟吃 CPU物体越多碰撞越贵接近 N² 增长。核心优化用简单碰撞体球/胶囊/盒别用 Mesh Collider用就勾 Convex、配置 Layer 碰撞矩阵关掉无用的层间碰撞最有效、静态物体别加 Rigidbody 也别移动、调大 Fixed Timestep、利用刚体休眠、Raycast 用 LayerMask NonAlloc 且别每帧狂射、少用 Stay 类回调。【动画】靠骨骼采样 动画混合 蒙皮吃 CPUAnimator 即使角色没动也在跑状态机评估。核心优化设置 Culling Mode 剔除看不见的动画最有效、远处角色降频/LOD、减少骨骼数量、大量角色人群用 GPU Instancing 顶点动画VAT绕开 CPU、Optimize Game Objects、简单动画别用重量级 Animator、参数按需设置且用 Hash 代替字符串、控制 Animator 数量。定位用 Profiler 的 Physics 模块和 Animator.Update 分辨到底是哪块的锅针对性优化核心口诀物理靠碰撞模拟吃CPU用简单碰撞体层矩阵静态标记降频动画靠骨骼采样吃CPU用Culling剔除远处降频GPU方案参数按需设Profiler定位对症下药 物理与动画优化速查表领域核心优化关键点物理-碰撞体用简单形状避免Mesh Collider物理-层矩阵关无用碰撞⭐Physics Settings物理-静态不加Rigidbody别移动静态碰撞物理-频率调Fixed Timestep别太大物理-查询LayerMaskNonAlloc别每帧狂射动画-剔除Culling Mode⭐不可见不更新动画-LOD远处降频骨骼数量减动画-大量GPU方案(VAT)绕开CPU动画-参数按需设Hash别每帧设 一句话记住核心物理——简单碰撞体 Layer 矩阵关无用碰撞 静态别动 Raycast 省着用。动画——Culling 剔除不可见 远处降频 LOD 大量角色用 GPU 参数按需设。两大 CPU 杀手Profiler 定位后对症下药 延伸CPU 优化的全景【物理与动画只是CPU优化的两块】 CPU优化的完整战场: ① 脚本逻辑: - 避免Update里重活 - 缓存组件引用 - 减少GC(字符串/装箱) ② 物理: ← 本篇 碰撞体/层矩阵/查询优化 ③ 动画: ← 本篇 剔除/LOD/GPU方案 ④ 渲染相关的CPU开销: - DrawCall/批处理 - 剔除(Culling) ⑤ GC与内存: - 减少堆分配 - 对象池 ↓ CPU优化 全方位减少每帧的计算量! 核心思想: 不做无用功、能省则省、能缓存则缓存