109.网格与动画资源优化

109.内存优化-资源优化-网格和动画


109.1 知识点

网格与动画优化的核心理念

减负、精简、按需加载。

  • 网格优化目标: 降低顶点处理负荷和 GPU 传输负担
  • 动画优化目标: 降低 CPU 蒙皮计算和内存占用
  • 核心矛盾: 视觉保真度 与 CPU/GPU 性能、内存占用 之间的平衡

网格资源导入优化

网格导入设置是优化的第一道关卡。

Mesh Compression(网格压缩)

级别 说明
Off 无压缩,最高精度,绝对精确,没有任何视觉损失
Low 非常轻微的压缩,对顶点数据的精度损失几乎不可见
Medium 平衡压缩率和视觉质量
High 激进地压缩顶点数据,追求最大程度的体积缩减

网格压缩的目的是减小网格资产在磁盘上的文件大小以及在运行时内存中的占用。它通过降低顶点数据的精度来实现,本质上是在内存、磁盘空间和顶点精度之间进行权衡。压缩的不是多边形数量,而是每个顶点的位置、法线、UV 等数据的存储精度。

过高压缩会带来闪烁、法线接缝、法线贴图异常等副作用。压缩带来的问题在静态模型上往往不明显,但在骨骼动画模型上会被放大,务必在动画状态下测试设置为 High 压缩级别的角色,观察关节处是否有抖动。

使用场景 推荐级别
重要角色、主角,会近距离观察 Low 或 Medium
主要道具,玩家会经常互动 Medium
大量使用的场景物件/远景物体 High

Read/Write(读写使能)

  • 勾选: CPU 和 GPU 都可访问网格数据
  • 不勾选: 仅 GPU 可访问,上传后释放 CPU 内存
  • 建议: 运行时不需要修改的网格务必取消勾选,许多内存飙升问题就出在忘记关这里

Optimize Mesh(优化网格)

通过重新组织网格数据来提高 GPU 的渲染效率。优化前就像把一本工具书的页码完全打乱,找每个工具都要翻来翻去;优化后就像把书按章节和索引整理好,查找工具时速度飞快。

选项 说明 适用场景
Everything 同时优化多边形顺序和顶点顺序,最全面的优化 默认推荐,能带来最好的性能提升
Polygon Order 只优化三角形的绘制顺序,不改变顶点的内存布局 Everything 导致问题时的折中方案
Vertex Order 只优化顶点在内存中的布局顺序,不改变三角形的绘制顺序 特殊需求

建议始终选择 Everything,出现渲染问题时再回退到 Polygon Order。

Generate Colliders(生成碰撞体)

  • 勾选: 自动生成 MeshCollider
  • 建议: 仅在必要时勾选,MeshCollider 性能开销大,简单碰撞用普通几何体 Collider

网格压缩决策流程

  • 重要角色 → Low、Medium Compression
  • 场景道具 → High Compression
  • 永远不需要修改的网格 → 不要勾选 Read/Write
  • 所有静态网格 → 始终选择 Optimize Mesh

顶点数据优化

减少顶点数量和顶点数据量,从源头抓起,在建模时就准备好。

顶点数量控制

使用 LOD(Level of Detail):根据距离使用不同精度的网格。

顶点数据精简

移除不必要的顶点属性:

  • 切线: 若完全没有法线贴图、各向异性的模型可移除
  • 顶点色: 无特殊着色需求的模型可移除
  • 多组 UV: 无光照贴图、细节贴图、流光、特殊采样等效果时可移除第二组 UV

顶点缓存优化

为了提升顶点缓存命中率,尽可能让三角形共享顶点。顶点缓存优化的基础在于良好的建模拓扑(从源头促进顶点共享),引擎的 Optimize Mesh 选项是在此基础上进行”整理”以发挥硬件的最佳性能,但它无法改变模型固有的、低效的拓扑结构。

实践配置示例

类型 策略
高端角色 保留所有顶点数据
场景道具 移除切线、顶点色等
远处物体 使用低模,移除所有额外顶点数据

动画资源导入优化

动画资源是内存和 CPU 的大户。

Animation Compression(动画压缩)

模式 说明
Off 无压缩,最高精度
Keyframe Reduction 减少关键帧数量
Optimal Unity 智能压缩,平衡质量和大小

建议角色动画用 Optimal,不重要动画用 Keyframe Reduction。

Rotation Error / Position Error / Scale Error

压缩误差阈值,值越大压缩越狠,质量损失越大:

使用场景 推荐误差值
主角核心动作、过场动画 低误差值(0.1 ~ 0.5)
NPC 常规动画 中等误差值(0.5 ~ 1.0)
远景小生物、次要特效 高误差值(1.0 ~ 2.0+)

Remove Constant Scale Curves(移除恒定缩放曲线)

自动检测并移除在整个动画时间段内没有发生变化的缩放曲线,可以减小动画文件体积和运行时内存占用,降低 CPU 开销。一个角色动画中,大部分骨骼可能只有旋转和位移变化,而缩放始终是 (1,1,1),这条不变的缩放曲线会一直被计算和存储。勾选此选项后,Unity 会在导入时删除这些冗余的恒定曲线。

动画系统运行时优化

Animator 的 Culling Mode(动画器剔除模式)

模式 说明
Always Animate 始终更新,即使不可见(性能最差)
Cull Update Transforms 不可见时停止根 Motion 更新
Cull Completely 不可见时完全停止动画(推荐)

动画控制器动画层数优化

  • 减少活跃的 Animator Layer 数量
  • 按需启用/禁用动画层

动画事件优化

  • 避免在每帧触发的事件中执行昂贵操作
  • 使用缓存,避免在事件中频繁查找组件

Humanoid vs Generic 动画类型

类型 特点 适用场景
Humanoid 人形动画,支持重定向,占用更多内存 仅人形角色
Generic 通用动画,更轻量,不支持重定向 其他所有情况

更多优化技巧

  1. GPU Skinning(GPU 蒙皮) — 将蒙皮计算从 CPU 转移到 GPU,大幅减少 CPU 开销。在 Project Settings → Other Settings → Rendering → GPU Skinning 中设置:CPU 模式在 CPU 上计算顶点变换;GPU 模式在 GPU 上计算;GPU(Batched) 在 GPU 上计算并合批优化。要求 Shader 支持和现代 GPU
  2. 动画简单化 — 对非关键角色使用简单动画(旋转、位移)而非骨骼动画
  3. 对象池 + 动画状态复用 — 对频繁创建销毁的动画对象使用对象池;复用 Animator Controller,通过参数控制不同状态
  4. 动画 LOD 系统 — 根据距离使用不同更新频率,比如通过脚本控制 Animator 的 API 调整更新模式和更新频率。远处角色降低动画更新频率(如 30fps → 15fps),不可见角色完全停止动画更新
  5. 蒙皮网格渲染器优化 — 减少骨骼数量(人形角色 ≤ 30 根,非人形角色尽可能少);使用 Enable GPU Instancing 对相同网格的多个实例进行合批

性能分析与监控

分析工具使用

  • Profiler → Rendering:查看顶点数量、SetPass Calls
  • Profiler → CPU Usage → Animation:监控动画系统 CPU 开销
  • Frame Debugger:分析每帧的绘制调用
  • Memory:查看 Mesh/AnimationClip 内存占用

关键性能指标

指标 移动端 PC 端
顶点数量(每帧) < 100K < 500K
骨骼数量(单个角色) < 30 根 < 100 根

此外还需监控 AnimationClip 内存占用和活跃 SkinnedMeshRenderer 数量。

内存优化

  • 使用 Addressables 管理动画资源
  • 及时卸载未使用的 AnimationClip
  • 监控 Mesh 内存占用,确保 Read/Write 关闭

总结

网格优化流程:

  1. 设置合适的压缩级别
  2. 取消 Read/Write(除非需要修改)
  3. 开启 Optimize Mesh
  4. 按需使用 LOD
  5. 精简顶点数据

动画优化流程:

  1. 选择合适的压缩格式(Optimal 推荐)
  2. 设置合理的压缩质量
  3. 配置 Animator Culling 模式
  4. 按需使用 GPU Skinning
  5. 实现动画 LOD 系统

109.2 知识点代码

Lesson109_内存优化_资源优化_网格和动画.cs

public class Lesson109_内存优化_资源优化_网格和动画
{
    #region 知识点一 网格与动画优化的核心理念

    // 减负、精简、按需加载
    // 网格优化目标:
    // 降低顶点处理负荷和 GPU 传输负担

    // 动画优化目标:
    // 降低 CPU 蒙皮计算和内存占用

    // 核心矛盾:
    // 视觉保真度 和 CPU/GPU 性能 和 内存占用 的平衡

    #endregion

    #region 知识点二 网格资源导入优化

    // 网格导入设置是优化的第一道关卡

    // 1.Mesh Compression(网格压缩)
    //   Off:无压缩,最高精度,绝对精确,没有任何视觉损失
    //   Low:施加非常轻微的压缩,对顶点数据的精度损失几乎不可见
    //   Medium:平衡压缩率和视觉质量
    //   High:激进地压缩顶点数据以追求最大程度的体积缩减
    //   作用:
    //   目的是减小网格资产在磁盘上的文件大小以及在运行时内存中的占用
    //   它通过降低顶点数据的精度来实现这一目标
    //   本质上是在内存、磁盘空间和顶点精度之间进行权衡
    //   压缩的不是多边形数量,而是每个顶点的位置、法线、UV 等数据的存储精度
    //   但是过高压缩会带来闪烁、法线接缝、法线贴图异常等等副作用
    //   压缩带来的问题在静态模型上往往不明显,但在骨骼动画模型上会被放大
    //   务必在动画状态下测试设置为 High 压缩级别的角色,观察关节处是否有抖动
    //   建议:
    //   重要角色、主角,会近距离观察 → Low 或 Medium
    //   主要道具,玩家会经常互动 → Medium
    //   大量使用的场景物件/远景物体 → High

    // 2.Read/Write(读写使能)
    //   勾选:CPU 和 GPU 都可访问网格数据
    //   不勾选:仅 GPU 可访问,上传后释放 CPU 内存
    //   建议:
    //   运行时不需要修改的网格务必取消勾选
    //   许多内存飙升问题就出在忘记关这里

    // 3.Optimize Mesh(优化网格)
    //   通过重新组织网格数据,来提高 GPU 的渲染效率
    //   优化前:就像把一本工具书的页码完全打乱,找每个工具都要翻来翻去
    //   优化后:就像把书按章节和索引整理好,查找工具时速度飞快

    //   Everything(优化所有内容):
    //   这是最全面、最激进的优化,它会同时优化 Polygon Order(多边形顺序)和 Vertex Order(顶点顺序)
    //   通常能带来最好的性能提升,可能会干扰一些依赖于特定顶点顺序的自定义着色器或脚本

    //   Polygon Order(优化多边形顺序):
    //   只优化三角形的绘制顺序,而不改变顶点的内存布局
    //   当脚本或着色器依赖于原始的顶点顺序时(这种情况比较罕见)
    //   作为一个折中方案,如果 Everything 导致问题,可以回退到此选项试试

    //   Vertex Order(优化顶点顺序):
    //   只优化顶点在内存中的布局顺序,而不改变三角形的绘制顺序

    //   建议:
    //   始终勾选 Everything,能提升渲染性能,出现渲染问题时再选择 Polygon Order

    // 4.Generate Colliders(生成碰撞体)
    //   勾选:自动生成 MeshCollider
    //   建议:仅在必要时勾选,MeshCollider 性能开销大,简单碰撞用普通几何体 Collider

    // 网格压缩决策流程:
    // 重要角色 → Low、Medium Compression
    // 场景道具 → High Compression
    // 永远不需要修改的网格 → 不要勾选 Read/Write
    // 所有静态网格 → 始终选择 Optimize Mesh(优化网格)

    #endregion

    #region 知识点三 顶点数据优化

    // 减少顶点数量和顶点数据量
    // 从源头抓起,在建模时就准备好的事情

    // 1.顶点数量控制
    //   使用 LOD(Level of Detail):根据距离使用不同精度的网格

    // 2.顶点数据精简
    //   移除不必要的顶点属性:
    //   切线:若完全没有法线贴图、各向异性的模型可移除
    //   顶点色:无特殊着色需求的模型可移除
    //   多组 UV:无光照贴图、细节贴图、流光、特殊采样等效果时可移除第二组 UV

    // 3.顶点缓存优化
    //   为了提升顶点缓存命中率,尽可能让三角形共享顶点
    //   顶点缓存优化的基础在于良好的建模拓扑(从源头促进顶点共享)
    //   引擎的 Optimize Mesh(优化网格)选项是在此基础上进行"整理"
    //   以发挥硬件的最佳性能,但它无法改变模型固有的、低效的拓扑结构

    // 实践配置示例:
    // 高端角色:保留所有顶点数据
    // 场景道具:移除切线、顶点色等
    // 远处物体:使用低模,移除所有额外顶点数据

    #endregion

    #region 知识点四 动画资源导入优化

    // 动画资源是内存和 CPU 的大户
    // 1.Animation Compression(动画压缩)
    //   Off:无压缩,最高精度
    //   Keyframe Reduction:减少关键帧数量
    //   Optimal:Unity 智能压缩,平衡质量和大小
    //   建议:角色动画用 Optimal,不重要动画用 Keyframe Reduction

    // 2.Rotation Error / Position Error / Scale Error
    //   压缩误差阈值,值越大压缩越狠,质量损失越大
    //   建议:
    //   主角核心动作、过场动画,使用低误差值(0.1 - 0.5)
    //   NPC 常规动画,使用中等误差值(0.5 - 1.0)
    //   远景小生物、次要特效,使用高误差值(1.0 - 2.0+)

    // 3.Remove Constant Scale Curves(移除恒定缩放曲线)
    //   自动检测并移除在整个动画时间段内没有发生变化的缩放曲线
    //   可以减小动画文件体积和运行时内存占用,降低 CPU 开销
    //   工作原理:
    //   一个角色动画中,大部分骨骼可能只有旋转和位移变化,而缩放始终是 (1,1,1)
    //   这条不变的缩放曲线会一直被计算和存储
    //   勾选此选项后,Unity 会在导入时删除这些冗余的恒定曲线

    #endregion

    #region 知识点五 动画系统运行时优化

    // 1.Animator 的 Culling Mode(动画器剔除模式)
    //   Always Animate:始终更新,即使不可见(性能最差)
    //   Cull Update Transforms:不可见时停止根 Motion 更新
    //   Cull Completely:不可见时完全停止动画(推荐)

    // 2.动画控制器动画层数优化
    //   减少活跃的 Animator Layer 数量
    //   按需启用/禁用动画层

    // 3.动画事件优化
    //   避免在每帧触发的事件中执行昂贵操作
    //   使用缓存,避免在事件中频繁查找组件

    // 4.Humanoid vs Generic 动画类型
    //   Humanoid:人形动画,支持重定向,占用更多内存
    //   Generic:通用动画,更轻量,不支持重定向
    //   选择:仅人形角色用 Humanoid,其他用 Generic

    #endregion

    #region 知识点六 更多优化技巧

    // 1.GPU Skinning(GPU 蒙皮)
    //   开启:将蒙皮计算从 CPU 转移到 GPU
    //         Project Settings → Other Settings → Rendering → GPU Skinning
    //         CPU: 在 CPU 上计算顶点变换
    //         GPU: 在 GPU 上计算顶点变换
    //         GPU(Batched): 在 GPU 上计算顶点变换,并合批优化
    //   优点:大幅减少 CPU 开销
    //   要求:Shader 支持,现代 GPU

    // 2.动画简单化
    //   对非关键角色使用简单动画(旋转、位移)而非骨骼动画

    // 3.对象池 + 动画状态复用
    //   对频繁创建销毁的动画对象使用对象池
    //   复用 Animator Controller,通过参数控制不同状态

    // 4.动画 LOD 系统
    //   根据距离使用不同更新频率
    //   比如通过脚本控制 Animator 的 API 调整更新模式和更新频率
    //   远处角色:降低动画更新频率(如 30fps → 15fps)
    //   不可见角色:完全停止动画更新

    // 5.蒙皮网格渲染器优化
    //   减少骨骼数量:人形角色 <= 30 根,非人形角色尽可能少
    //   使用 Enable GPU Instancing:对相同网格的多个实例进行合批

    #endregion

    #region 知识点七 性能分析与监控

    // 1.分析工具使用
    //   Profiler → Rendering:查看顶点数量、SetPass Calls
    //   Profiler → CPU Usage → Animation:监控动画系统 CPU 开销
    //   Frame Debugger:分析每帧的绘制调用
    //   Memory: Mesh/AnimationClip

    // 2.关键性能指标
    //   顶点数量:每帧 < 100K(移动端),< 500K(PC 端)
    //   骨骼数量:单个角色 < 30 根(移动端),< 100 根(PC 端)
    //   动画内存:监控 AnimationClip 内存占用
    //   SkinnedMeshRenderer 数量:活跃蒙皮网格数量

    // 3.内存优化
    //   使用 Addressables 管理动画资源
    //   及时卸载未使用的 AnimationClip
    //   监控 Mesh 内存占用,确保 Read/Write 关闭

    #endregion

    #region 总结

    // 网格优化流程:
    // 1.设置合适的压缩级别
    // 2.取消 Read/Write(除非需要修改)
    // 3.开启 Optimize Mesh(优化网格)
    // 4.按需使用 LOD
    // 5.精简顶点数据

    // 动画优化流程:
    // 1.选择合适的压缩格式(Optimal 推荐)
    // 2.设置合理的压缩质量
    // 3.配置 Animator Culling 模式
    // 4.按需使用 GPU Skinning
    // 5.实现动画 LOD 系统

    #endregion
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏