
CPU 蒙皮 vs GPU 蒙皮 — 小白都能看懂的对比教程如果你做过 Unity 游戏尤其是有大量角色的游戏你一定听过蒙皮这个词。这篇文章用最白的话讲清楚什么是蒙皮、CPU 蒙皮和 GPU 蒙皮有什么区别、为什么 DOTS 要干掉 CPU 蒙皮。一、先搞懂什么是蒙皮角色是怎么动起来的想象一个提线木偶骨骼木偶里面的铁丝骨架你看不见但它在皮肤木偶外面的布套你看见的蒙皮把布套绑在骨架上骨架一动布套跟着动的过程游戏角色完全一样美术做A model askeleton (bone hierarchy) askin (mesh vertices)When playing an animation, the skeleton poses → the skin deforms accordingly蒙皮就是算皮肤怎么跟着骨架变形的过程谁在算这个两个选择方式谁干活外号CPU 蒙皮CPU中央处理器来算旧方案GPU 蒙皮GPU显卡来算新方案、DOTS 方案二、前置知识骨骼矩阵是什么一句话骨骼矩阵 一根骨头当前的位置 旋转 缩放你角色有 30 根骨头头、脖子、肩膀、手臂……每根骨头每帧都有一个矩阵4×4 的表格记录位置x, y, z—— 骨头在哪旋转绕 x/y/z 转了多少度—— 骨头朝哪缩放拉长了还是压扁了—— 骨头多大30 根骨头 30 个骨骼矩阵 一个骨骼矩阵数组动画播放 每帧刷新这些矩阵的值比如抬手动画 肩膀骨骼矩阵的旋转值变了三、CPU 蒙皮SkinnedMeshRenderer—— 老方案3.1 它是怎么工作的每一帧的流程① Animator 采样动画 → 算出每根骨骼位置/旋转 ↓ ② 计算 30 个骨骼矩阵 ↓ ③ CPU 开始干活 ┌─────────────────────────────────────────────┐ │ 遍历所有顶点几千个 │ │ 每个顶点 │ │ 查哪 4 根骨头影响它 │ │ 查权重骨头A 影响 50%骨头B 影响 30%... │ │ 用骨骼矩阵算出新位置 │ │ 全部算完 → 得到一张全新变形后的网格 │ └─────────────────────────────────────────────┘ ↓ ④ 调用 Graphics.UpdateMeshVertices 把整张新网格上传到 GPU 显存 ↓ ⑤ GPU 只负责画顶点已经是算好的了3.2 核心问题在哪每个角色每帧都要CPU 算几千个顶点上传整张顶点数据到 GPU一个角色还好1000 个角色就是 1000 倍1000 人 × 3000 顶点 × 每秒 60 帧 每秒 1.8 亿次顶点运算CPU 单线程 1000 人 × 每帧上传完整网格 显存带宽爆炸更致命的是没法合批每个角色独立算完 → 独立顶点 Buffer → 独立 DrawMesh1000 人 1000 个 DrawMesh → CPU 提交压力直接炸裂3.3 一句话总结CPU 蒙皮 CPU 算完所有顶点上传给 GPUGPU 只负责画。四、GPU 蒙皮DOTS 方案—— 新方案4.1 核心思路反过来让 GPU 自己算顶点CPU 只算骨架姿态。① Animator 采样动画 → 算出每根骨骼位置/旋转 ↓ ② Burst 多线程批量计算所有角色的骨骼矩阵 1000 个角色一起算非常快 ↓ ③ 顶点呢不碰 CPU 不算顶点 ↓ ④ 调用 Material.SetMatrixArray 把骨骼矩阵数组传给 GPU ↓ ⑤ GPU 顶点着色器里 读取原始顶点 骨骼权重 骨骼矩阵 GPU 自己算顶点变形 ↓ ⑥ 同材质角色自动 Instancing 合批4.2 关键区别项目CPU 蒙皮GPU 蒙皮CPU 算啥骨骼矩阵 所有顶点只算骨骼矩阵传给 GPU 啥整张变形后的顶点只传几十个矩阵GPU 算啥只负责画自己算顶点变形顶点是否需要重复上传每帧重新上传一次上传永久驻留4.3 为什么快① CPU 工作量暴跌CPU 蒙皮算矩阵快 算顶点极慢 GPU 蒙皮算矩阵快② 没有每帧顶点上传原始顶点、权重、索引永远存在 GPU 显存不用每帧传。CPU → GPU 的数据从几万个顶点变成几十个矩阵。③ 合批合批合批所有同材质的角色共享同一个网格、同一个材质。GPU 可以 InstancingCPU 蒙皮1000 角色 1000 DrawMesh GPU 蒙皮1000 角色 几十个 DrawMesh甚至 1 个五、最直白的对比餐厅比喻CPU 蒙皮GPU 蒙皮厨房 CPU厨师CPU洗菜、切菜、炒菜全干完厨师CPU只写菜单骨骼矩阵服务员 数据通道传一整桌菜整张顶点网格只传一张菜单骨骼矩阵数组顾客 GPU顾客直接吃只负责画顾客自己按菜单炒菜GPU 自己算顶点哪个快显然是只写菜单快。一句话记区别方式口诀CPU 蒙皮动画 → CPU 改顶点 → 上传顶点 → GPU 画GPU 蒙皮动画 → 只传矩阵 → GPU 改顶点 → 批量画六、数据流图对比CPU 蒙皮数据流主线程/C 内部 GPU ┌──────────────────┐ ┌──────────┐ │ 动画采样 │ │ │ │ ↓ │ 上传 │ 直接画 │ │ 算骨骼矩阵 │ ────────→ │ 已变形 │ │ ↓ │ 整张顶点 │ 的顶点 │ │ 逐顶点 CPU 蒙皮 │ │ │ └──────────────────┘ └──────────┘GPU 蒙皮数据流Burst/Job 系统 GPU ┌──────────────────┐ ┌──────────────────┐ │ 动画采样 │ │ │ │ ↓ │ 只传矩阵 │ 顶点着色器里 │ │ 算骨骼矩阵数组 │ ────────→ │ 读权重 读矩阵 │ │不算顶点 │ │ GPU 自己算变形 │ └──────────────────┘ │ 然后画 │ └──────────────────┘七、实战为什么 DOTS / ECS 必须用 GPU 蒙皮千人同屏场景你做了一个 MMORPG目标是同屏 1000 个玩家。如果用 CPU 蒙皮SkinnedMeshRenderer1000 角色 × 5000 顶点 每帧 500 万顶点 CPU 运算 1000 角色 1000 次顶点上传 1000 角色 ≈ 1000 个 DrawMeshCPU 直接满载帧率个位数。如果用 GPU 蒙皮 DOTSCPU 只算 1000 套骨骼矩阵Burst 多线程极快 GPU 自己算顶点显卡就是干这个的 同材质合批 → 几十个 DrawMeshCPU 占用极低同屏千人流畅。你的项目要做的事① 删掉所有 SkinnedMeshRenderer ② 预存骨骼权重数据 ③ 每帧用 Job 系统批量算骨骼矩阵 ④ 用 Material.SetMatrixArray 传给 GPU ⑤ GPU Instancing 批量绘制八、灵魂四问Q1CPU 蒙皮完全没用了吗A小项目1-2 个角色完全够用。只有大规模同屏才需要换 GPU 蒙皮。Q2GPU 蒙皮有缺点吗A有。需要自己写 Shader、管理矩阵数组、处理 LOD。实现成本比 CPU 蒙皮高。Q3Unity 内置支持 GPU 蒙皮吗AUnity 有GPU Skinning选项Player Settings 里开启但它和 DOTS 合批方案比还是不够极致。DOTS 方案是完全自己控制的。Q4BindPose 是啥A角色 T-pose 站立时的默认矩阵。GPU 蒙皮时Shader 里要用当前矩阵 × BindPose 逆矩阵算出正确的变形。九、最终总结背下来CPU 蒙皮GPU 蒙皮谁算顶点CPUGPU显卡传给 GPU 什么整张变形后的网格几十个骨骼矩阵每帧上传量几万个顶点几十个矩阵CPU 负载 高 极低合批能力❌ 不能合批✅ Instancing 合批适用场景1-2 个角色大规模同屏千人实现难度 自带零代码 需要自己实现一句话终极结论CPU 蒙皮 包办到底CPU 全干GPU 只画GPU 蒙皮 分工协作CPU 只管骨骼GPU 自己算顶点DOTS 大规模同屏必须走 GPU 蒙皮没有第二个选择。参考Unity Graphics.UpdateMeshVertices 引擎内部调用机制 / Unity SkinnedMeshRenderer 工作原理 / GPU Skinning vs CPU Skinning Benchmark