Unity性能优化 -- 性能分析工具

  • Stats窗口
  • Profiler窗口
  • Memory Profiler
  • 其他性能分析工具(Physica Debugger 窗口,Import Activity 窗口,Code Coverage 窗口,Profile Analyzer 窗口,IMGUI Debugger 窗口)

Stats 统级数据窗口

game窗口

可以初步查看游戏运行时,当前一帧的各项性能

  • Audio表示音频的数据
  • Level表示声音强度,单位是分贝,也就是dB。声音太大或太小都会影响玩家体验。
  • DSP load表示数字信号处理器的负载。播放的声音越多、声音的采样率越高、声音效果越复杂,本变量的数值都会越大。应尽量避免这项数据过大。
  • Clipping表示音频的裁剪情况。当音频信号超过设备支持的最大范围时,该音频信号会被裁剪。裁剪之后,该音频会出现一定程度失真的现象。应尽量避免这项数据过大。
  • Stream load表示音频流的负载情况。音频的流式加载是指以持续的方式从音频源获取音频数据,而不是一次性加载全部数据。流式加载的主要优势是可以实时地处理和播放音频,无需等待全部数据加载完成。应尽量避免这项数据过大。
  •  FPS表示帧率,209.5FPS(4.8ms)表示平均每秒播放209.5张画面,平均每4.8毫秒播放一张画面。
  • CPU的指标表示CPU处理一帧的时间。例如CPU:main 4.6ms render thread 0.5ms表示Unity的主线程处理这一帧所花费的时间是4.6毫秒,主线程主要负责游戏逻辑的更新,例如检测用户的输入、更新游戏对象的位置、碰撞检测等。在渲染线程处理这一帧所花费的时间是0.5毫秒,渲染线程负责显示游戏画面。
  •  Batches表示处理的绘制调用(Draw Call)批次的总数。 应尽量避免这项数据过大。
  • Saved by batching表示有多少个绘制调用(Draw Call)被合并到了批次。应尽量让这项数据大。
  • Tris表示当前摄像机视锥体的范围内三角面的个数。应尽量避免这项数据过大。
  • Verts表示当前摄像机视锥体的范围内网格顶点的个数。 应尽量避免这项数据过大。
  •  在3D建模软件中创建的模型导入到Unity后,该模型在Unity中显示的三角面和网格顶点的数量和在3D建模软件中的可能不同。因为3D建模软件和Unity对模型的三角面和网格顶点的计算方式可能是不一样的。
  •  Screen表示当前的屏幕分辨率,以及屏幕的内存占用量。例如Screen:1920×1080 - 23.7MB表示当前屏幕分辨率是1920×1080,屏幕占用了23.7MB的内存。 应尽量避免这项数据过大。
  •  SetPass calls表示在当前摄像机的渲染过程中,Unity切换着色器通道(Shader Pass)来渲染游戏对象的次数。一个着色器(Shader)可以包含多个着色器通道,每个着色器通道可以通过不同的方式来渲染游戏对象。但每次切换着色器通道都会消耗一定的性能。  应尽量避免这项数据过大。
  • Shadow casters表示摄像机画面中有多少个游戏对象产生了阴影。同一个游戏对象产生较多的阴影,可能会被算作多个Shadow casters 应尽量避免这项数据过大。
  • Visible skinned meshes表示当前摄像机中有多少个可见的蒙皮网格。应尽量避免这项数据过大。
  • Animation components playing表示当前场景中有多少个Animation组件正在播放动画。播放动画会消耗性能。应尽量避免这项数据过大。没用的Animator组件和Animation组件可以考虑删掉。因为即使只有空的动画,Animator组件和Animation组件也会根据自己的工作流程进行每帧的计算和更新,以检查当前动画状态和过渡条件,这样就会消耗不必要的性能。

Draw Call 是什么?

要将游戏中的物体显示到屏幕上,就需要绘制它们。绘制之前,会先由CPU计算出它们的位置、
颜色等信息,然后发送绘制指令给GPU。GPU接受到CPU发过来的绘制指令,就会按照要求绘制东西在屏幕上。

Draw Call是指CPU向GPU发送绘制指令的过程,一个Draw Call就是CPU向GPU发送的一组绘制指令,可以绘制出一个或多个物体。

Draw Call有时也被简称为DC

Draw Call太多会使游戏变卡,优化的时候可以想办法降低Draw Call。

要降低Draw Call,可以使用合批技术,例如动态合批和静态合批。将多个Draw Call合批成一个批次(Batch),再由CPU发送给GPU,这样可以提升游戏性能。

垂直同步

垂直同步用于将游戏的帧率限制为显示器的刷新率,可以防止游戏画面在高速移动时的画面撕裂现象,使游戏画面更加平滑和连贯。

如果不启用垂直同步,当游戏的帧率高于显示器的刷新率时,图像的一部分可能会在显示器刷新之前更新,导致画面上出现明显的断裂线。而启用垂直同步后,图形处理器会等待显示器完成一次完整的刷新,然后再发送下一帧图像,确保每个图像帧都在刷新之前完全绘制,从而消除了撕裂现象。

但是启用垂直同步会消耗一些性能,也可能会出现卡顿的现象,要根据自己的实际情况来决定是否启用。

网格 蒙皮

网格用来定义一个模型的形状、大小和表面细节等信息,模型的所有顶点、线、面共同构成了这个模型的网格。蒙皮网格是一个与骨骼绑定的网格,这个网格可以发生形变和做出各种动作。一个网格 在没有蒙皮之前是不能发生形变的,也不能做出各种动作的。但是在成功蒙皮之后,这个网格就可以发生形变和做出各种动作。

Profiler 窗口

打开方式: Window——Analysis——Profiler

使用性能分析器进行分析时,其自身也是会消耗性能的。如果想获得更加准确的数据,可以使用独立性能分析器,即Profiler(Standalone Process)

打开Profiler(Standalone Process)窗口的方法:
Window——Analysis——Profiler(Standalone Process)

独立性能分析器的运行不会影响收集的数据,因此可以获得更加准确的数据。它的用法和Profiler窗口相同,但是启动它的时间比打开Profiler窗口的时间长。

打开Profiler窗口后,运行Unity,再点击Profiler窗口上方的圆形按钮,就会开始收集当前开始的每一帧的性能,再点一下那个圆形按钮,则会停止收集,此时就可以双击右上部分的一个位置选中一帧,然后看这一帧的情况,一般我们可以选择波峰的一帧,这样容易看出性能开销大的原因。也可以推动时间轴,或者点击上方圆形按钮右侧的三个按钮,查看其它帧的情况。上方的Frame表示当前正在查看的帧数以及收集的总帧数,例如Frame:738/963表示一共收集了963帧,当前查看的是第738帧。

每一项左侧的颜色方块表示该项是显示的,如果点击颜色方块,则右侧会隐藏该项的数据。

如果不要显示某个模块的数据,可以点击左上角的“Profiler Modules”,取消勾选它,这样在性能分析器收集数据的时候,也不会收集这些数据,可以减少性能分析器的开销。如果要重新显示某个模块的数据,则勾选它即可。点击Restore Defaults会恢复默认的设置。点击小齿轮,再点击Add,可以自定义一个新的模块,并自定义这个模块要分析的性能,且可以在上方的输入框处改名,然后点击Save Changes可以保存。如果要删除它,则点击Delete Module即可删除它,同样,点击Save Changes可以保存。

如果要清除当前收集的所有帧的数据,则可以点击上方的“Clear”。再次点击Profiler窗口上方的圆形按钮,就会开始收集当前开始的每一帧的性能,再点一下那个圆形按钮,则会停止收集,此时就可以双击右上部分的一个位置选中一帧,然后看这一帧的情况。

选中一帧后,除了可以在右侧看到这一帧的情况,还可以在下方看到这一帧更加具体的情况。

要找出造成性能开销的因素,可以尝试禁用场景中的游戏对象。如果禁用后,看到性能提升了,则说明问题出在这个游戏对象身上,优化的时候就可以从它身上下手。

        点击圆形按钮左侧的下拉菜单,可以选择分析什么的性能。如果选择Play Mode,则会分析游戏在运行时的性能,如果选择Edit Mode,则会分析编辑器模式下游戏的性能。
        如果用手机的数据线成功连接到电脑,在手机上运行Unity的游戏,这里会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
        也可以让手机和电脑都连接同一个wifi,这样一来,这里也会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
        注意,无论是用wifi还是数据线,构建项目时必须在Build Settings窗口中勾选Development Build和Autoconnect Profiler。

选择上方的Clear on Play,则在每次重新运行游戏的时候,都会清空收集的数据,以便我们重新开始收集这一次的数据。

如果要保存收集到的数据到本地,方便之后查看,可以点击右上方的图标来保存。右上方也有一个图标可以读取之前保存的数据。

        选择上方的Deep Profile,然后重新启动性能分析器,则性能分析器收集数据的时候,会把所有C#代码中的方法的信息也收集过来。例如我们自己写的C#脚本,里面的方法只要被调用了,就会被收集过来,方便我们从性能分析器查看它们的性能。在Profiler窗口选择CPU Usage模块,选中一帧,然后在下面选择Hierarchy,右侧选择Main Thread,再在右侧的搜索栏处搜索该方法的名字,就可以找到它,并查看它的性能。
        注意,使用Deep Profile会耗费较大的性能,可能会导致性能分析器的运行变慢。小项目这样做是可以的,但是如果项目较大,这样做可能会导致性能分析器运行过慢。如果要分析某一段代码的性能,可以使用Profiler.BeginSample方法和Profiler.EndSample方法

        选中Deep Profile右侧的Call Stacks按钮,这样在收集性能数据的时候,每一帧都会记录该方法的的调用栈信息。GC.Alloc、UnsafeUtility.Malloc、JobHandle.Complete是Unity的方法,启用Call Stacks且勾选它们后,如果Unity有调用它们,则可以在Hierarchy或Raw Hierarchy右侧的搜索框中搜索到它们,这样就可以查看它们的性能了。
        GC.Alloc表示GC的内存分配情况。
        UnsafeUtility.Malloc(Persistent)用于在内存中分配指定大小的未初始化内存块。这个方法会直接在堆上分配内存,并可以绕过自动内存管理功能,需要手动管理内存的生命周期和释放。一般情况下,只有在处理非托管内存的特定场景下才会使用UnsafeUtility.Malloc方法。
        JobHandle.Complete表示Job的完成情况。这里的Job是指Unity的Job System的一组特定的任务。

点击右上角的三点,有一些选项可以选择。
        Color Blind Mode表示色盲模式,开启后会调整Profile窗口的颜色,照顾色盲用户。
        Show Stats for 'current frame'开启后,当点击Frame:XXX/XXX左侧的按钮,从而选中最后一帧,则会显示最后一帧的统计信息。
        Preferences,点击后会打开Project Settings窗口,用于设置性能分析器的一些属性。
                Frame Count,开始收集性能的数据时,每次最多可以查看多少帧。例如数值是300,则表示最多可以查看300帧。
                Show Stats for 'current frame',勾选后,则在右上角的三点会出现Show Stats for 'current frame'供我们选择。
                Default recording state,选择Enable,则重启Unity再打开Profiler窗口,如果此时的模式是Edit Mode,则会自动开始点击圆形按钮,开始收集数据。选择Disabled,则重启Unity再打开Profiler窗口,需要手动点击圆形按钮,才会开始收集数据。选择Remember,则会按照当前圆形按钮是启用还是禁用来决定下一次重启Unity再打开Profiler窗口时,该圆形按钮是否启用。
                Default editor target mode on start,选择Play Mode,则重启Unity再打开Profiler窗口,左上方会选择Play Mode,即在播放模式下才会收集数据。如果选择Edit Mode,则重启Unity再打开Profiler窗口,左上方会选择Edit Mode,即在编辑器模式下收集数据。
                Custom connection ID,当有多个Unity项目的实例同时运行,它们都要使用性能分析器来分析性能,则可以通过这个Custom connection ID来区分它们。

CPU Usage模块:
        下方窗口可以选择Timeline、Hierarchy、Raw Hierarchy
         选择Timeline,可以通过时间轴的方式查看这一帧中CPU依次干了什么。
         选择Hierarchy,可以查看CPU在这一帧中做的事情所消耗的性能和所花费的时间。Total表示一共占用了CPU使用情况的百分之几。Self表示自身的代码占用了CPU使用情况的百分之几,调用其它方法的代码不算在内的。Calls表示被调用了几次。GC Alloc表示GC分配的内存,当一个对象被释放后,它GC分配的内存不会马上被回收,所有GC分配的内存的总量达到一定程度,会触发GC,此时垃圾回收器才会把这些内存回收,不过同时也会造成游戏卡一下。Time ms表示一共耗时多少毫秒。Self ms表示表示自身的代码耗时多少毫秒,调用其它方法的代码不算在内的。
        选择Raw Hierarchy比起Hierarchy会单独列出更多信息,Hierarchy实际上是把这些信息合并了。

调用栈(Call Stack)

是计算机程序在执行过程中记录函数调用的一种数据结构。

调用栈是一个栈结构,即先进后出。它用于记录程序执行过程中,每个函数被调用的情况。

当一个函数被调用时,它的相关信息,如函数名、参数、返回地址等,会被添加进调用栈中。当该函数执行完成后,相应的信息会从调用栈中移除。通过不断添加和移除函数调用的信息,调用栈就记录了程序执行的顺序

调用栈对于程序调试和分析非常有用。当程序出现错误或异常时,可以通过查看调用栈来确定错误发生的位置和函数调用的顺序。调试器通常会显示当前调用栈的信息,以帮助开发人员查看函数的执行过程并找出发生异常的原因。

托管内存与非托管内存

托管内存是由垃圾回收器自动管理的内存,当达到一定量时,会由垃圾回收器自动释放它们。

托管内存存放在托管堆中。托管堆是一种用于存储和管理托管对象的内存区域。每当创建一个新的托管对象时,托管堆就会分配内存空间给这个对象,并记录这个对象的信息。当托管对象不再被引用,垃圾回收器会自动将其标记为垃圾,并在适当的时候回收其占用的内存空间。

非托管内存不会自动被回收,它们需要我们程序员写代码去管理和释放它们。

非托管内存并不固定存储在一个地方,它们往往分散存储在不同的地方,例如操作系统的内存、临时缓冲区等。

DOTS(Data-Oriented Technology Stack)

是Unity引擎中的一个新的编程模型和工具集。它旨在提供更高性能、更可扩展和更并行化的游戏开发体验。

  • ECS框架:ECS是一种用于组织和管理游戏对象的方式。它将游戏对象分解为实体(Entity)、组件(Component)和系统(System)。这种模式更加适合于并行处理和优化,可以提高游戏性能。
  • Job System(作业系统):Job System允许开发者将任务并行化,利用多核处理器的能力。它通过将任务划分为小的作业(jobs)并在多个线程上并发执行来提高性能。Job System还可以与ECS结合使用,使得开发者可以更好地控制游戏的行为。
  • Burst Compiler(突发编译器):Burst Compiler是一种高性能的C#编译器,可以将C#代码转换为高效的本机代码,以进一步提高游戏的性能。

DOTS的目标是为游戏开发者提供更好的性能和可扩展性,并更好地利用现代硬件的并行能力。它适用于需要处理大量实体和需要高性能的游戏项目。

Frame Debugger窗口

也叫帧调试器窗口,用于查看每一帧的画面是如何渲染出来的,可以详细查看这一帧的绘制过程。

打开Frame Debugger面板的方式:
Window——Analysis——Frame Debugger

按下“Enable”,则会启动帧调试,此时如果运行了游戏,则会自动暂停,然后当前这帧的渲染情况可以在这个窗口中查看。

上方的 X of X 表示绘制过程中有多少步,可以查看下一步或上一步。

如果要禁用帧调试,可以按下“Disable”。

用Frame Debugger窗口查看当前一帧的每一步时,可以配合Stats窗口使用,以此来确定哪一个物体造成的性能开销较大。

绘制的步骤越少,性能越好。

Frame Debugger窗口也能看到每一帧的Shader信息,但是需要有一定Shader基础才能看懂。

        大多数平台都支持帧调试器的使用,可以用手机的数据线成功连接到电脑,在手机上运行Unity的游戏,Frame Debugger窗口中会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
        也可以让手机和电脑都连接同一个wifi,这样一来,Frame Debugger窗口中也会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
        但是要注意,构建时必须在Project Settings窗口中勾选“Development Build”。而且有些平台可能不支持Frame Debugger的使用,例如WebGL平台。

参考:siki学院性能优化课程,挂不了链接,会被识别为广告

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一些swift问题

写得比较快,如果有问题请私信。 序列化和反序列化 反序列化的jsonString2只是给定的任意json字符串 private func p_testDecodeTable() {let arr ["recordID123456", "recordID2"]// 序列化[string] -> json datalet jsonData try? JSO…

VMware虚拟机Debian扩展磁盘

一、 版本 VMware:Workstation 17 Pro虚拟机:Debian11 二、 VMware虚拟机扩展 虚拟机关机状态快照或者备份:以免扩容失败导致文件丢失虚拟机——设置——硬盘——磁盘使用工具——扩展——扩展磁盘容量——设置为想要的大小 三、 虚拟机…

GameFramework教程☀️福利(五):关于该框架的一些意义

文章目录 📢 不同模式的意义本章探讨GF这样编写的意义和使用场景。 📢 不同模式的意义 最近在做一个app,现在在调研阶段。 代码上后期可能用华佗进行C#热更新。 在调研华佗打包完的热更代码如何和UI AB结合起来时,看到了: "> 从这一点可以延伸理解出,当我们使…

【漏洞复现】某平台-QRcodeBuildAction-LoginSSO-delay-mssql-sql注入漏洞

《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect 《Web安全》h…

Armv8的安全启动

目录 1. Trust Firmware 2. TF-A启动流程 3. TF-M启动流程 3.1 BL1 3.2 BL2 4.小结 在之前汽车信息安全 -- 再谈车规MCU的安全启动文章里,我们详细描述了TC3xx 、RH850、NXPS32K3的安全启动流程,而在车控类ECU中,我们也基本按照这个流程…

vue+django+neo4j航班智能问答知识图谱可视化系统

🔞 友友们,有需要找我,懂的都懂 🩵 基于NLP技术知识图谱的航班知识智能问答 🩵 技术架构:vue django mysql neo4j 🩵 数据:航班数据7万多条 🩵 vue知识图谱的模糊查询…

DICOM标准:核医学图像模块属性——核医学(Nuclear Medicine, NM)DICOM标准详解

目录 引言 1. NM 序列模块(NM Sequence Module) 1.1 NM序列模块属性 2. NM 设备模块(NM Equipment Module) 2.1 NM设备模块属性 3. NM 图像模块(NM Image Module) 3.1 NM图像模块属性 3.2 帧增量指针…

ViT面试知识点

文章目录 VITCLIPBlipSAMFast TransformerYOLO系列问题 BatchNorm是对一个batch-size样本内的每个特征做归一化,LayerNorm是对每个样本的所有特征做归一化。 Layer Normalization(层归一化,简称LayerNorm)是一种在深度学习中常用…

WPF使用Prism框架首页界面

1. 首先确保已经下载了NuGet包MaterialDesignThemes 2.我们通过包的项目URL可以跳转到Github上查看源码 3.找到首页所在的代码位置 4.将代码复制下来&#xff0c;删除掉自己不需要的东西&#xff0c;最终如下 <materialDesign:DialogHostDialogTheme"Inherit"Ide…

CTFshow之信息收集第1关到10关。详细讲解

得而不惜就该死&#xff01; --章总 开始新的篇章&#xff01; 零、目录 一、实验准备 1、ctf网站&#xff1a;ctf.show 2、工具&#xff1a;chrome浏览器、hackbar插件 3、burpsuite抓包工具 二、实验技巧 &#xff08;一&#xff09;F12摸奖 源码泄露 &#xff08;二…

企业CRM管理系统PHP源码/PHP客户关系CRM客户管理系统源码

系统功能实现 1、 公海管理:公海类型、客户公海。 2、 线索管理:我的线索、线索列表、线索状态、线索来源。 3、 客户管理:我的客户、客户列表、成交客户、行业类别、预查、地区列表、客户状态、客户级别。 4、 业绩订单:订单列表、我的订单。 5、 系统设置:系统设置…

40.第二阶段x86游戏实战2-初识lua

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

DAY17|二叉树Part03|LeetCode: 530.二叉搜索树的最小绝对差、501. 二叉搜索树中的众数、236.二叉树的最近公共祖先

目录 LeetCode: 530.二叉搜索树的最小绝对差 基本思路 有序数组法 C代码 双指针法 C代码 LeetCode: 501. 二叉搜索树中的众数 哈希法 C代码 双指针法 C代码 LeetCode: 236.二叉树的最近公共祖先 基本思路 C代码 LeetCode: 530.二叉搜索树的最小绝对差 力扣代码链…

「Mac畅玩鸿蒙与硬件27」UI互动应用篇4 - 猫与灯的互动应用

本篇将带领你实现一个趣味十足的互动应用&#xff0c;用户点击按钮时猫会在一排灯之间移动&#xff0c;猫所在的位置灯会亮起&#xff08;on&#xff09;&#xff0c;其余灯会熄灭&#xff08;off&#xff09;。应用会根据用户的操作动态更新灯光状态和文本提示当前亮灯的位置&…

【网络】套接字编程——UDP通信

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;UDP网络服务器简单模拟实现。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;…

黑马官网2024最新前端就业课V8.5笔记---HTML篇

Html 定义 HTML 超文本标记语言——HyperText Markup Language。 标签语法 标签成对出现&#xff0c;中间包裹内容<>里面放英文字母&#xff08;标签名&#xff09;结束标签比开始标签多 /拓展 &#xff1a; 双标签&#xff1a;成对出现的标签 单标签&#xff1a;只有开…

openfoam中生成的3d案例提取得到slice后的2d案例

问题&#xff1a; 由于前期准备做3d的案例&#xff0c;并且模拟也比较费时间&#xff0c;现在生成了几十份3d的数据&#xff0c;但是现在只想要2d的数据来演示&#xff0c;该如何提取或者转换呢&#xff1f; 解决方法&#xff1a; 1.说明图片中的每个2d视图的points都是恒定不…

使用 Sortable.js 库 实现 Vue3 elementPlus 的 el-table 拖拽排序

文章目录 实现效果Sortable.js介绍下载依赖添加类名导入sortablejs初始化拖拽实例拖拽完成后的处理总结 在开发过程中&#xff0c;我们经常需要处理表格数据&#xff0c;并为用户提供便捷的排序方式。特别是在需要管理长列表、分类数据或动态内容时&#xff0c;拖拽排序功能显得…

STM32 + CubeMX + 硬件SPI + W5500 +UDP

这篇文章记录一下STM32W5500UDP的调试过程&#xff0c;实现UDP数据的接收与发送。 目录 一、W5500模块介绍二、Stm32CubeMx配置三、Keil代码编写1、添加W5500驱动代码到工程&#xff08;添加方法不赘述&#xff0c;驱动代码可以在官网找&#xff09;2、在工程中增加代码&#…