当前位置: 首页 > news >正文

Unity 性能优化 之 编辑器创建资源优化(UGUI | 物理 | 动画)

Unity 之 性能优化 -- 编辑器创建资源优化

  • Unity UI性能的四类问题
    • Canvas画布
    • Canvas Re-batch过程
    • UGUI渲染细节
    • Re-Build过程
    • UI字体
      • 动态字体与字体图集
  • UI优化建议
    • 使用Canvas的基本准则
    • UGUI射线(Raycaster)优化
    • UI控件优化注意事项
  • 物理
    • Unity中的物理解决方案
    • Unity中的Physics全局配置
    • Unity中的物理组件Trigger与Collider
    • Unity中的物理组件Collider部分的优化
    • Unity中的物理组件RigidBody部分的优化
    • Unity中的RayCast与Overlap部分的优化
  • 动画
    • Animation的一些细节
    • Animator的一些细节
    • Animator注意事项
    • Internal Animation Update
    • Animator VS Animation
    • Playable API VS Animator
    • 解决方案选择

Unity UI性能的四类问题

  1. Canvas Re-batch 时间过长
  2. Canvas Over-dirty, Re-batch次数过多
  3. UI生成网格顶点时间过长
  4. UI Shader中GPU片源着色器的利用率过高 (Fill-rate overutilization)

Canvas画布

Canvas负责管理UGUI元素,负责UI渲染网格的生成与更新,并向GPU发送DrawCall指令。

Canvas Re-batch过程

  1. 根据UI元素深度关系进行排序
  2. 检查UI元素的覆盖关系
  3. 检查UI元素材质并进行合批

UGUI渲染细节

  • UGUI中渲染是在Transparent半透明渲染队列中完成的,半透明队列的绘制顺序是从后往前画,由于UI元素做Alpha Blend,我们在做UI时很难保障每一个像素不被重画,UI的Overdraw太高,这会造成片元着色器利用率过高,造成GPU负担。
  • UI SpriteAtlas图集利用率不高的情况下,大量完全透明的像素被采样也会导致像素被重绘,造成片元着色器利用率过高;同时纹理采样器浪费了大量采样在无效的像素上,导致需要采样的图集像素不能尽快的被采样,造成纹理采样器的填充率过低,同样也会带来性能问题。

Re-Build过程

  • 在WillRenderCanvases事件调用PerformUpdate::CanvasUpdateRegistry接口
    • 通过ICanvasElement.Rebuild方法重新构建Dirty的Layout组件
    • 通过ClippingRegistry.Cullf方法,任何已注册的裁剪组件Clipping Compnents(Such as Masks)的对象进行裁剪剔除操作
    • 任何Dirty的 Graphics Compnents都会被要求重新生成图形元素
  • Layout Rebuild
    • UI元素位置、大小、颜色发生变化
    • 优先计算靠近Root节点,并根据层级深度排序
  • Graphic Rebuild
    • 顶点数据被标记成Dirty
    • 材质或贴图数据被标记成Dirty

UI字体

  • 避免字体框重叠,造成合批打断

  • 字体网格重建

    • UIText组件发生变化时
    • 父级对象发生变化时
    • UIText组件或其父对象enable/disable时
  • TrueTypeFontImporter

    • 支持TTF和OTF字体文件格式导入

在这里插入图片描述

动态字体与字体图集

  • 运行时,根据UIText组件内容,动态生成字体图集,只会保存当前Actived状态的 UIText控件中的字符
  • 不同的字体库维护不同的Texture图集
  • 字体Size、大小写、粗体、斜体等各种风格都会保存在不同的字体图集中(有无必要,影响图集利用效率,一些利用不多的特殊字体可以采用图片代替或使用Custom Font,Font Assets Creater创建静态字体资源)
  • 当前Font Texture不包含UIText需要显示的字体时,当前Font Texture需要重建
  • 如果当前图集太小,系统也会尝试重建,并加入需要使用的字形,文字图集只增不减
  • 利用Font.RequestCharacterInTexture可以有效降低启动时间

UI优化建议

使用Canvas的基本准则

  • 将所有可能打断合批的层移到最下边的图层,尽量避免UI元素出现重叠区域
  • 可以拆分使用多个同级或嵌套的Canvas来减少Canvas的Rebatch复杂度
  • 拆分动态和静态对象放到不同Canvas下。
  • 不使用Layout组件
  • Canvas的RenderMode尽量Overlay模式,减少Camera调用的开销

UGUI射线(Raycaster)优化

  • 必要的需要交互UI组件才开启“Raycast Target”
  • 开启“Raycast Targets”的UI组件越少,层级越浅,性能越好
  • 对于复杂的控件,尽量在根节点开启“Raycast Target”
  • 对于嵌套的Canvas,OverrideSorting属性会打断射线,可以降低层级遍历的成本

UI控件优化注意事项

  • 不需要交互的UI元素一定要关闭Raycast Target选项

  • 如果是较大的背景图的UI元素建议也要使用Sprite的九宫格拉伸处理,充分减小UI Sprite大小,提高UI Atlas图集利用率

  • 对于不可见的UI元素,一定不要使用材质的透明度控制显隐,因为那样UI网格依然在绘制,也不要采用active/deactive UI控件进行显隐,因为那样会带来gc和重建开销

  • 使用全屏的UI界面时,要注意隐藏其背后的所有内容,给GPU休息机会。

  • 在使用非全屏但模态对话框时,建议使用OnDemandRendering接口,对渲染进行降频。

  • 优化裁剪UI Shader,根据实际使用需求移除多余特性关键字。

  • 滚动视图Scroll View优化

    • 使用RectMask2d组件裁剪 – 注意不要使用不规则的图形
    • 使用基于位置的对象池作为实例化缓存


物理

Unity中的物理解决方案

  • Box2D (2D默认)
  • Nvidia PhysX (3D默认)
  • Unity Physics (更精简高效的物理功能子集,专为处理大规模物体和繁多碰撞而设计)
  • Havok Physics for Unity (经过大量3A游戏验证、具有更高性能与稳定性的商业物理引擎插件,在2022版本正式加入Unity官方支持的生产管线、能够与Unity自身物理引擎良好协作)。

Unity中的Physics全局配置

  • 重点配置
    Layer Collision Matrix;
  • 场景物理回调相关:
    Queries Hit Backfaces、Queries Hit Triggers、Contact Pairs Mode、Auto Simulation、Auto Sync Transforms;
  • 场景物理需求相关:
    Gravity、Default Contact Offset、Bounce Threshold、Sleep Threshold、Enable Adaptive Force、Enable Enhanced Determinism、Enable Unified Heightmaps;
  • 场景物理精度相关:
    Default Solver Iterations、Default Solver Velocity Iterations、Broadphase Type、Friction Type、Solver Type;
  • 其他:
    Default Material、World Bounds、Cloth Inter-Collision、Contacts Generation

“总的来说,Sweep and Prune Broadphase 是一种经典的碰撞检测算法,适用于处理大量静态对象;Multibox Pruning Broadphase 是一种改进的算法,更适用于处理动态对象和大量对象;而 Automatic Box Pruning 则是一种自动选择最佳算法的方便选项。”

Unity中的物理组件Trigger与Collider

  • Trigger与Collider
    • Trigger对象的碰撞会被物理引擎所忽略,通过OnTriggerEnter/Stay/Exit函数回调
    • Collider对象由物理引擎触发碰撞,通过OnCollisionEnter/Stay/Exit函数回调
    • Trigger对象不需要RigidBody组件,Collider对象必须至少有一个Collider对象有RigidBody组件
    • Trigger对象更高效

Unity中的物理组件Collider部分的优化

  • 尽量少使用MeshCollider,可以用简单Collider代替,即使用多个简单Collider组合代替也要比复杂的MeshCollider来的高效
  • MeshCollider是基于三角形面的碰撞
  • MeshCollider生成的碰撞体网格占用内存也较高
  • MeshCollider即使要用也要尽量保障其是静态物体
  • 可以通过PlayerSetting选项中勾选Prebake Collision Meshes选项来在构建应用时预先Bake出碰撞网格。

Unity中的物理组件RigidBody部分的优化

  • Kinematic与RigidBody
    • Kinematic对象不受物理引擎中力的影响,但可以对其他RigidBody施加物理影响。
    • RigidBody完全由物理引擎模拟来控制,场景中RigidBody数量越多,物理计算负载越高
    • 勾选了Kinematic选项的RigidBody对象会被认为是Kinematic的,不会增加场景中的RigidBody个数
    • 场景中的RigidBody对象越少越好

Unity中的RayCast与Overlap部分的优化

  • Unity物理中RayCast与Overlap都有NoAlloc版本的函数,在代码中调用时尽量用NoAlloc版本,这样可以避免不必要的GC开销
  • 尽量调用RayCast与Overlap时要指定对象图层进行对象过滤,并且RayCast要还可以指定距离来减少一些太远的对象查询
  • 此外如果是大量的RayCast操作还可以通过RaycastCommand的方式批量处理,充分利用JobSystem来分摊到多核多线程计算。


动画

Animation、Animator、Playable Api

  • Animation组件为Legacy动画系统思路,相关文件为Animation Clip。Legacy动画系统对单一轻量动画文件有轻便的实现。
  • Animator组件为Mechanim动画系统思路,相关文件为Animator Graph。Mechanim动画系统提供了更强大和灵活的动画控制功能,包括基于状态机的动画过渡、层次动画混合、动画事件等功能。
  • Playable API是一套用于控制和管理动画、音频和其他时间相关内容的高级API,相关文件为Playable Asset ( Playable \ Playable Graph )。
    Playable可以是动画片段、音频片段或自定义逻辑片段,它们可以被组合、混合和连接,以创建复杂的交互式时间线;
    通过创建Playable Graph,可以将各种Playable对象连接在一起,构建出整个动画或音频系统的结构。Playable Graph是一个图形化的数据结构,它描述了Playable对象之间的关系和交互方式。

Animation的一些细节

  • 播放单个AnimationClip速度,Legacy Animation系统更快,因为老系统是直接采样曲线并直接写入对象Transform
  • 针对动画的缩放曲线比位移、旋转曲线开销更大
  • 常数曲线不会每帧写入场景,更高效

Animator的一些细节

  • 不要使用字符串来查询Animator
  • 使用曲线标记来处理动画事件
  • 使用Target Marching函数来协助处理动画
  • 将Animator的CullingMode设置成Based On Renderers来优化动画,并禁用SkinMesh Renderer的Update When Offscreen属性来让角色不可见时动画不更新

Animator注意事项

  • 使用AnimationEvent来处理动画事件;
  • 使用Target Marching函数来协助处理动画;
  • 在人型动画中,使用Target Marchin的方法能够相对平滑得对目标关节节点进行IK实现。
  • 不要使用字符串来查询Animator;
    例如,相对于SetBool(“targetName”,val)的查询赋值方式,更应结合animator.parameters与SetBool(index,val)的方式缓存索引并根据索引赋值。
  • 将Animator的Culling Mode设置成Cull Update Transforms或Cull Completely来优化动画,并禁用SkinMesh Renderer的Update When Offscreen属性来让角色不可见时动画不更新。
  • Culling Mode影响动画的剔除状态,当动画被剔除时,其上的AnimationEvent不再被调用。
  • 选择Cull Update Transforms选项时,当动画对象不在摄像机视野内时,停止更新对象的变换信息,但仍会保持动画的播放状态。这样可以节省一些性能,因为动画对象的变换信息不再被更新,但动画仍会持续播放。
  • 选择Cull Completely选项时,动画状态将完全停止,动画回调等亦无法收到。

Internal Animation Update

在这里插入图片描述

Animator VS Animation

  • Animation可以将任何对象属性制作成Animation Clip, Animator是将Animaiton Clip组织到状态机流程图中使用
  • Animation与Animator播放动画时的效率是有个临界点的,这个临界点是根据动画曲线条数来的,当动画曲线条数小于这个临界点时Animation快,当动画曲线条数大于这个临界点时Animator快
  • 当Cpu核数较少时,Animation播放动画有优势,当Cpu核数较多时,Animator表现会更好
  • Animator Controller Graph中的所有动画节点的Animation Clip都会载入到内存中,当有海量动画状态机节点时,内存开销较大

Playable API VS Animator

Playable API优点

  • 支持动态动画混合,可为场景中的对象提供自己的动画,并可以动态添加到PlayableGraph当中使用
  • 允许创建播放单个动画,而并不会产生创建和管理AnimatorController资源所涉及的开销,可更加灵活的控制PlayableGraph的数据流,可以插入自定义的AimationJob。
  • 可以控制动画文件加载策略,按需加载、异步加载等
  • 允许用户动态创建混合图,并直接逐帧控制混合权重(甚至可以混合AniationClip与AnimatorController动画)
  • 可以运行时动态创建,根据条件添加可播放节点。而不需要提前提供一套PlayableGraph运行时启动和禁用节点,可以做到自由度更高的override机制
  • 可加载自定义配置数据,更加方便的和其他游戏系统整合

Playable API缺点

  • 没有直接使用Animator直观
  • 混合模式没有现成的,需要自己实现
  • 需要开发更多的配套工具
  • 有一定学习成本

解决方案选择

  • 一些简单、少量曲线动画可以使用Animation或动画区间库如Dotween\iTween等完成,如UI动画,Transform动画等。
  • 角色骨骼蒙皮动画如果骨骼较少,Animation Clip资源不多,对动画混合表现要求不高的项目可以采用Legacy Animation。注意控制总体曲线数量
  • 一些角色动画要求与逻辑有较高的交互、并且动画资源不多的项目可以直接用Animator Graph完成
  • 一些动作游戏,对动画混合要求较高、有一些高级动画效果要求、动画资源量庞大的项目,建议采用Animator+Playable API扩展Timeline的方式完成。

本文整理自:Metaverse大衍神君《Unity性能优化》


文章转载自:

http://GHvJAD1C.brwgp.cn
http://wq8J0kC4.brwgp.cn
http://oQr1cV1u.brwgp.cn
http://IUHORtFf.brwgp.cn
http://T2KnV0ub.brwgp.cn
http://Kweo24O5.brwgp.cn
http://v6gtG2sR.brwgp.cn
http://iDJavZDY.brwgp.cn
http://p7PvpjxS.brwgp.cn
http://Z4DUWHMW.brwgp.cn
http://mGX0yBM8.brwgp.cn
http://HUtJFt5i.brwgp.cn
http://AokZwRSY.brwgp.cn
http://OltGzDV2.brwgp.cn
http://A3iqQdq0.brwgp.cn
http://10S2Muo7.brwgp.cn
http://lve0FUvu.brwgp.cn
http://A8ERVkGP.brwgp.cn
http://FXX358Ah.brwgp.cn
http://ee7NS8tA.brwgp.cn
http://OaYO8UyC.brwgp.cn
http://PbEuvbVG.brwgp.cn
http://CvFPwH8J.brwgp.cn
http://piOeIvaw.brwgp.cn
http://5Uu2rURI.brwgp.cn
http://9VBxRHtR.brwgp.cn
http://Px0bKeKU.brwgp.cn
http://71lvG2Jy.brwgp.cn
http://1flZt3he.brwgp.cn
http://trhovRcW.brwgp.cn
http://www.dtcms.com/a/384391.html

相关文章:

  • PostgreSQL——分区表
  • Elastic APM 高级特性:分布式追踪与机器学习优化
  • Ubuntu 服务器配置转发网络访问
  • Redis 数据结构源码剖析(SDS、Dict、Skiplist、Quicklist、Ziplist)
  • C#通讯之网络通讯 TCP UDP
  • 响应时间从5ms到0.8ms:威迈斯AI+DSP协同架构的突破与工程实践
  • 《WINDOWS 环境下32位汇编语言程序设计》第16章 WinSock接口和网络编程(2)
  • 算法--插入排序
  • 领码方案|权限即数据:企业系统中的字段级访问控制架构实战(Ver=1.0)
  • 【面试场景题】支付金融系统与普通业务系统的一些技术和架构上的区别
  • 数证杯顺心借JAVA网站重构详细版(服务器取证基础考点+检材+题目+重构视频)
  • 【Unity】【Photon】Fusion2中的玩家输入系统 学习笔记
  • Vue3 + Three.js 实战:自定义 3D 模型加载与交互全流程
  • 【Leetcode hot 100】102.二叉树的层序遍历
  • [Windows] 微软 .Net 运行库离线安装包 | Microsoft .Net Packages AIO_v09.09.25
  • java通过RESTful API实现两个项目之间相互传输数据
  • C++基础(13)——list类的模拟实现
  • C#/.NET/.NET Core技术前沿周刊 | 第 54 期(2025年9.8-9.14)
  • 快速上手 Jenkins
  • 【C++】STL--List使用及其模拟实现
  • Go语言双向链表list.List详解
  • 机器学习-Boosting
  • Jenkins运维之路(Jenkins流水线改造Day02-2-容器项目)
  • 【C++STL】list的详细用法和底层实现
  • Elastic APM 与 Elasticsearch 集成:构建完整可观测性栈
  • 从零搭建MCP Server:Python开发、部署与应用全流程实战
  • Mac本地Docker拉取镜像本地挂载项目
  • 购物车效果
  • 在Ubuntu 18.0.4 编译最新版Python-3.13.7
  • 如何在ubuntu下用pip安装aider,解决各种报错问题