【unity小技巧】unity最全的性能优化方案分享以及如何进行性能测试(2024/11/11更新)

news2024/11/19 18:02:44

文章目录

  • 前言
  • 一、性能分析软件
    • 1、Draw Call
      • 什么是Draw Call
      • 如何查看Draw Call数量
    • 2、分析帧调试器
    • 3、Statistics统计面板
  • 二、优化手段
    • 1、关于图集、材质、层级的处理,减少DrawCall
    • 2、批处理
    • 3、音乐处理
    • 4、减少沉余资源和重复资源
    • 5、渲染优化(GPU)
      • Lod技术
      • Occlusion Culling-遮挡剔除
      • 光照贴图
      • 合并Mesh
    • 6、CPU性能优化
      • 代码执行优化
    • 7、性能测试
      • Vector2.Distance 和 sqrMagnitude哪个好?
      • 动画切换优化
      • shader属性优化
    • 8、URP渲染器资产优化
    • 9、对象池优化
    • 10、 删除没必要的空函数
    • 11、图片、音乐音效、贴图等素材压缩
    • 12、ScriptableObject优化参数
  • 完结

前言

unity能够跨平台主要是内置了mono虚拟机这也是unity游戏包体大运行卡的原因。

功能的实现必不可缺,当然也要注意程序性能的优化。随着项目越来越大,优化变得至关重要,它能确保你的游戏任然可以快速流畅地运行。如果想知道如何对unity进行性能优化以及如何进行性能测试,那就继续往下看吧。

一、性能分析软件

1、Draw Call

什么是Draw Call

Draw Call是Cpu向GPU发起的一种在屏幕上绘制内容的请求。问题是,准备Unity Draw Call会占用CPU大量的时间和精力。Unity必须将场景内容转换为GPU可以理解的格式。这个过程开销最昂贵的部分是设置正确的渲染参数,例如纹理,着色器,网格等。

具体过程就是:设置颜色–>绘图方式–>顶点坐标–>绘制–>结束,所以在绘制过程中,如果能在一次DrawCall完成所有绘制就会大大提高运行效率,进而达到优化的目的。

如何查看Draw Call数量

可以通过分析器查看Draw Call数量
在这里插入图片描述

在这里插入图片描述

2、分析帧调试器

在这里插入图片描述
在这里插入图片描述

3、Statistics统计面板

在这里插入图片描述

在这里插入图片描述

二、优化手段

1、关于图集、材质、层级的处理,减少DrawCall

点击运行游戏,打开分析帧调试器
在这里插入图片描述
然后点击启用工具,逐步查看Unity如何将图像渲染到屏幕上,我们可以看到有五个绘制调用,分别是背景、地板、敌人、玩家和玩家的武器
在这里插入图片描述
如果我们可以使用更少的绘制调用来实现相同的结果,它肯定会更快,我们可以使用Sprite Atlas来做到这一点在这里插入图片描述
把所有的资源都拖入,进行打包(注意这里属性和图片差不多,如果你是像素素材同样可以选择点类型,无压缩进行优化)
在这里插入图片描述
打包效果
在这里插入图片描述
我们再回去分析帧调试器查看,你会看到我们只有三个绘制调用
在这里插入图片描述
既然前面打包了,那么为什么不是一个呢,你可以看到它没有将敌人与玩家进行批处理,因为它们具有不同的材质
在这里插入图片描述
如果我们没必要使用不同的材质,我们可以选择把所有的材质换成一样的
在这里插入图片描述
这样的话,可以看到就仅仅绘制了一次,这明显加快了GPU绘制
在这里插入图片描述

2、批处理

在这里插入图片描述
在这里插入图片描述
开启动态静态批处理
在这里插入图片描述

在这里插入图片描述
Batches:批处理可让引擎尝试将多个对象的渲染组合到一个内存块中以便减少由于资源切换而导致的 CPU 开销。
Saved by batching:合并的批次数。为确保良好的批处理,应尽可能在不同对象之间共享材质。更改渲染状态会将批次分成具有相同状态的组。

比如我新增3个cube
在这里插入图片描述
默认Batches是4,Saved by batching是0
在这里插入图片描述
我们可以将3个cube进行静态合批,它们肯定是共用一个材质的
在这里插入图片描述
优化后效果,Batches是2,Saved by batching是2
在这里插入图片描述
据我了解合批的技术分为4种,我这里只是举例了一种,具体可以查看这篇文章,我觉得写的挺详细的,这里就不再补充了:
关于Unity四种合批技术详解

3、音乐处理

长时间音乐(背景音乐)压缩格式mp3
短时间音乐(音效)非压缩格式wav
在这里插入图片描述
在这里插入图片描述

4、减少沉余资源和重复资源

  • Resources目录下的资源不管否被I用,都会打包进安装包不使用的资源不要放在Resources自录下
  • 不同目录下的相同资源文件,如果都被引用,那么都会打包进资源包,造成沉余,保证同一个资源文件在项目中只存放在一个目录位置

5、渲染优化(GPU)

注意:我们可以通过verts和Tris查看视野内的顶点个数

verts表示摄像机视野内的顶点个数
Tris是三角面个数

天空盒也占有顶点个数,这里我删除了天空盒和除相机外的其他物体,你可以看到,场景中的Tis数量变为2,verts数量变为了4,这是由于摄像机存在的关系,删掉它,你就会发现Tris和Verts都变为0了。
在这里插入图片描述

Lod技术

如果模型一直使用同样的精细模型,会造成性能的浪费。比如下面三个模型
在这里插入图片描述
显示网格,查看模型精细程度
在这里插入图片描述
如果距离相机比较远的话,看起来其实是一样的,但是精细的模型肯定会更加消耗性能
在这里插入图片描述
Lod技术就是实现模型离得远自动使用最粗糙的模型,离得近使用精细的模型

实现,添加组件LOD Group
在这里插入图片描述
拖入模型lod0放置最精细的模型,lod2放置最粗糙的模型
在这里插入图片描述
随着相机的远近unity会自动切换不同的模型
在这里插入图片描述
我们可以拖动模型距离的占比,拉动相机查看演示效果
在这里插入图片描述

Occlusion Culling-遮挡剔除

只渲染在视野内的游戏物体,可以很大的优化我们的性能

勾选所有需要遮挡剔除的物体
在这里插入图片描述
生成一些遮挡剔除的数据
在这里插入图片描述
在这里插入图片描述
bake完之后,会生成一些网格,这些网格是进行遮挡剔除计算的,计算某一个物体是否在视野内,在视野内就渲染,不在视野内就不渲染
在这里插入图片描述
如果后期增加物体,都要进行bake重新烘培

移动相机查看效果
在这里插入图片描述
在这里插入图片描述
看batches变化
在这里插入图片描述

光照贴图

添加多个点光源,光照的计算是比较消耗性能的
在这里插入图片描述
如果我们把光照提前进行计算渲染,做出贴图,就可以很大的节省我们的性能

实现,勾选所有会被光照影响的物体
在这里插入图片描述
记得将所有的光源模式选择为bake烘培模式,Intensity强度也可以调小
在这里插入图片描述
烘培光照
在这里插入图片描述
默认是自动烘培,我们可以选择取消勾选Auto Generate,进行手动烘培
在这里插入图片描述
点击后会生成一个光照贴图信息
在这里插入图片描述
烘培后就可以禁用之前的光照了
在这里插入图片描述

结果
在这里插入图片描述

合并Mesh

合并模型我们可以使用模型软件(比如blender)
【blender小技巧】如何拆分模型、合并和删除模型,删除多余骨骼

也可以通过unity书写代码实现
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
运行效果
在这里插入图片描述
紫色是没有材质,指定材质即可
在这里插入图片描述
但是取消运行又消失了,我们可以在edit编辑器模式下运行,就可以保存合并的模型了

6、CPU性能优化

代码执行优化

我们经常会有书写这样的代码,比如新增EnemyBehavior.cs脚本挂载在敌人身上,这里在Update中每一帧都调用敌人面向玩家等操作,但是这完全是资源的浪费,在播放模式下没有必要在每帧上都这样做
在这里插入图片描述
运行状态下,打开Profiler 分析器
在这里插入图片描述
只需单击图表上的任意位置,我们的游戏就会暂停,以便我们可以对其进行分析,可以看到目前EnemyBehavior的更新占用了1.2%CPU使用率
在这里插入图片描述
这时候我们可以选择使用脚本委托和定时器控制它的更新频率,比如新增Ticker脚本,没过0.2秒调用TickEvent方法
在这里插入图片描述
逻辑不在Update中调用了,注册委托每0.2s调用一次
在这里插入图片描述
在这里插入图片描述
可以看到敌人是仍然总是面向玩家,但不是每帧都运行该逻辑,运行频率被降低了,但它并没有对游戏中敌人的行为产生明显的影响
在这里插入图片描述

7、性能测试

但是当涉及到某些代码片段时,仅用这些王具很难判断出什么实际上性能更高,有时您只需要自己测试一些东西,所以让我向您展示如何设置基准测试,来让您运行自己的测试

新增性能测试的类

using UnityEngine;
using System.Diagnostics;

// 用于性能测试的类
public class BenchMarker : MonoBehaviour
{
    [Range(0, 1000000)]
    [SerializeField] private float _iterations; // 迭代次数
    private BenchMarkTest _benchMarkTest; // 性能测试对象
    private Stopwatch sw; // 计时器

    // 在启动时获取BenchmarkTest组件
    private void Awake()
    {
        _benchMarkTest = GetComponent<BenchMarkTest>(); // 获取BenchmarkTest组件
    }

    // 执行测试的方法
    public void RunTest()
    {
        sw = Stopwatch.StartNew(); // 创建并启动计时器

        for (int i = 0; i < _iterations; i++)
        {
            _benchMarkTest.PerformBenchmarkTest(); // 执行性能测试
        }

        sw.Stop(); // 停止计时器
        UnityEngine.Debug.Log(sw.ElapsedMilliseconds + "ms"); // 输出测试时间
    }
}

Vector2.Distance 和 sqrMagnitude哪个好?

在Unity中,Vector2.Distance 和 sqrMagnitude 都是用来计算向量之间距离的方法,但它们的性能特性略有不同。

新增脚本,这里距离判断我们使用了Vector2.Distance,实际它的性能很差,因为它在内部计算中使用了开方运算 Mathf.Sqrt,开方运算通常比较昂贵,尤其是在大量计算时会消耗较多的计算资源。
在这里插入图片描述
点击测试
在这里插入图片描述
可以看到它平均需要执行390毫秒左右
在这里插入图片描述
我们现在换成性能更高的办法.sqrMagnitude进行距离判断,sqrMagnitude 属性返回向量的平方长度,与Vector2.Distance 方法不同,sqrMagnitude 不进行开方操作,因此它的计算代价更低。
在这里插入图片描述
重新测试发现,平均快了几毫秒左右
在这里插入图片描述
事实证明,我们可以继续使用Vector2.Distance 进行距离计算,因为它的可读性更高且对性能的影响似乎可以忽略不计

动画切换优化

通常我们都是这样进行动画切换
在这里插入图片描述
测试效果
在这里插入图片描述
但是其实有更好的办法,其实Unity获取这个动画字符串后会在幕后对其进行哈希处理,所以之后我们可以通过只做一次来节省时间,所以在这里我们可以提前对动画字符串进行哈希处理
在这里插入图片描述
可以看到,节约了近30毫秒的性能
在这里插入图片描述

shader属性优化

我们也想给改变shader属性来执行相同的操作,比如这里实现更改敌人的材质的颜色
在这里插入图片描述
改变颜色
在这里插入图片描述
测试结果,可以看到大概需要610ms左右
在这里插入图片描述
让我们尝试同样对字符串进行哈希处理
在这里插入图片描述
结果,发现速度加快了将近一半
在这里插入图片描述

8、URP渲染器资产优化

在URP渲染器资产中,如果你不需要深度纹理(Depth Texture)或不透明纹理(Opaque Texture )可以将其关闭,因为这些纹理最终会根据您的相机所看到的内容绘制纹理的深度或不透明度。如果你关闭它们,最终会优化大量不必要的内存
在这里插入图片描述

9、对象池优化

但如果您进行了大量实例化和销毁操作例如,如果您有一个带有大量子弹的游戏,那么您将需要实现个对象池系统,参考:【Unity小技巧】Unity探究自制对象池和官方内置对象池(ObjectPool)的使用

10、 删除没必要的空函数

如果你的脚本中有空函数,请删除它们,每个函数也会有一点开销成本,即使它实际上没有执行任何内容
在这里插入图片描述

11、图片、音乐音效、贴图等素材压缩

合理压缩素材会很大的减低我们的内存

比如先看看我的背景没有压缩,它是6.8MB
在这里插入图片描述
低质量压缩它是1.1MB
在这里插入图片描述
ps:合理的使用压缩,确保它不会明显降低你的画面质量

12、ScriptableObject优化参数

不同的敌人实例之间更改这些变量,现在当我点击播放时,这些脚本中的每一个都将有自己的实例,并且在这些类实例中的每一个上这些变量将在内存中拥有自己的副本,并且对于这种情况完全是浪费
内存中拥有自己的副本,并且对于这种
这里我们可以使用ScriptableObject
在这里插入图片描述
配置
在这里插入图片描述
这样我们就不会为这些变量的创建数十几个副本存放在内存中,它只是位于ScriptableObject上的一个副本,每个敌人都只指向该ScriptableObject的对象

即使你想要实现不同的敌人配置,你也只需创建另一个ScriptableObject的对象资产,绑定它并修改参数即可
在这里插入图片描述

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

[STM32]从零开始的STM32 HAL库环境搭建

一、前言 之前在搭建STM32的标准库环境时就告诉过大家&#xff0c;开发STM32的方式主要有三种。一种是最原始但是效率最高的寄存器开发&#xff0c;另一种是效率仅次于寄存器难度相对较低的标准库开发&#xff0c;最后一种是最为简单但是程序效率最低的HAL库开发。如果对于初学…

阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_技术趋势

目录 文献基本信息 序言 1 发展概况 2 重点技术发展 2.1 人工智能技术 2.1.1 应用深化 2.1.2 作战效能提升 2.2 航空技术 2.2.1螺旋桨设计创新 2.2.2 发射回收技术进步 2.3 其他相关技术 2.3.1 远程控制技术探 2.3.2 云地控制平台应用 3 装备系统进展 3.1 无人作…

python爬虫(二)爬取国家博物馆的信息

import requests from bs4 import BeautifulSoup# 起始网址 url https://www.chnmuseum.cn/zx/xingnew/index_1.shtml # 用于存储所有数据 all_data [] page 1 global_index 1 # 定义全局序号变量并初始化为1 while True:html_url requests.get(url).textif requests.get…

FPGA 第6讲 简单组合逻辑多路选择器

时间&#xff1a;2024.11.11-11.14 一、学习内容 1.组合逻辑 组合逻辑是VerilgHDL设计中一个重要组成部分。从电路本质上讲&#xff0c;组合逻辑电路的特点是输出信号只是当前时刻输入信号的函数&#xff0c;与其他时刻的输入状态无关&#xff0c;无存储电路&#xff0c;也没…

性能超越Spark 13.3 倍,比某MPP整体快数十秒 | 多项性能指标数倍于主流开源引擎 | 云器科技发布性能测试报告

云器Lakehouse正式发布性能测试报告 &#x1f3c5;离线批处理&#xff1a;在复杂批处理任务中&#xff0c;云器Lakehouse相较Spark表现出13.31倍性能提升。 &#x1f3c5;即席查询&#xff1a;在交互式分析场景下&#xff0c;云器Lakehouse相较Trino表现出9.84倍性能提升。 &am…

Frida反调试对抗系列(四)百度加固

本文只是交流技术&#xff0c;如有侵权请联系我删除。 知识星球&#xff1a;https://t.zsxq.com/kNlj4 前言&#xff1a; 上一篇文章我们提到 我们使用github开源魔改好的frida server 但是仍然有一些厂商的server不能通过&#xff0c;那么这篇文章针对百度加固 进行快速通…

利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能

某需求&#xff1a; 要求在任务截止日期的前3天时&#xff0c;系统自动给用户发一条消息提醒。 用定时任务的话感觉很不舒服。间隔时间不好弄。不能精准卡到那个点。 由于系统简单&#xff0c;没有使用消息列队&#xff0c;也不能使用延时队列来做。 用Timer的话开销还挺大的&a…

通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

目录 通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制 一、引言 二、语义搜索与 MongoDB Atlas 的背景 三、MongoDB Atlas 的向量搜索功能 1. 向量搜索的实现方式 2. 典型操作示例 四、RAG 在 MongoDB Atlas 的应用 1、RAG是什么 2、RAG 的实现过程 3、RA…

【graphics】图形绘制 C++

众所周知&#xff0c;周知所众&#xff0c;图形绘制对于竞赛学僧毫无用处&#xff0c;所以这个文章&#xff0c;专门对相关人员教学&#xff08;成长中的码农、高中僧、大学僧&#xff09;。 他人经验教学参考https://blog.csdn.net/qq_46107892/article/details/133386358?o…

Excel使用-弹窗“此工作簿包含到一个或多个可能不安全的外部源的链接”的发生与处理

文章目录 前言一、探讨问题发生原因1.引入外部公式2.引入外部数据验证二、问题现象排查及解决1.排查公式2.排查数据验证3.特殊处理方式总结前言 作为一种常用的办公软件,Excel被大家所熟知。尽管使用了多年,有时候在使用Excel时候也会发生一些不太常见的现象,需要用心核查下…

递归(3)----力扣40组合数2,力扣473火柴拼正方形

给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 示例 1: 输入: candidates [10,1,2,7,6,1…

CCF-第七届AIOps国际挑战赛-季军方案分享|北航-EasyRAG

历经4个月的时间&#xff0c;从初赛赛道第1&#xff0c;复赛赛道第2&#xff0c;到最后决赛获得季军&#xff0c;这一路我们团队收获了很多实践经验&#xff0c;也结识了不少业界的RAG研究者&#xff0c;受益匪浅。应组委会邀请&#xff0c;本文介绍一下我们EasyRAG方案的亮点和…

Spring Boot出现java: 错误: 无效的源发行版:16的解决方式

第一步&#xff1a; 修改为SDK的目标字节码版本 第二步&#xff1a;CtrlShiftAltS进入项目结构 第三步&#xff1a;pom.xml文件中 在网上搜索和自己SDK适配的Springboot版本&#xff0c;1.8对应的是2.7.1&#xff08;可以用&#xff09; 修改Java版本为1.8 最后的最后&a…

Redis学习 ——缓存

文章目录 一、Redis缓存的介绍二、Redis缓存问题2.1 缓存穿透2.2 缓存击穿2.3 缓存雪崩2.4 双写一致性2.5 缓存持久化RDBAOF 三、缓存数据管理3.1 数据过期策略3.2 数据淘汰策略 一、Redis缓存的介绍 我们在日常的代码编写中比较少使用到Redis&#xff0c;但是如果涉及到了比较…

【开源免费】基于Vue和SpringBoot的在线考试系统(附论文)

本文项目编号 T 624 &#xff0c;文末自助获取源码 \color{red}{T624&#xff0c;文末自助获取源码} T624&#xff0c;文末自助获取源码 网络的广泛应用给生活带来了十分的便利。所以把在线考试管理与现在网络相结合&#xff0c;利用java技术建设在线考试系统&#xff0c;实现…

git-.git目录解析

目录 .git目录下的文件信息 logs&#xff1a;记录各个分支日志记录 refs&#xff1a;记录本地分支、远程分支、tag标签最新commitID config: 配置信息&#xff0c;详细内容解析看下面介绍HEAD: 工作空间当前所在分支 inde文件: 它又常被称为“暂存区”或“缓存区”。这个文件…

sglang 部署Qwen2VL7B,大模型部署,速度测试,深度学习

sglang 项目github仓库&#xff1a; https://github.com/sgl-project/sglang 项目说明书&#xff1a; https://sgl-project.github.io/start/install.html 资讯&#xff1a; https://github.com/sgl-project/sgl-learning-materials?tabreadme-ov-file#the-first-sglang…

前端pdf预览方案

前端pdf预览方案 pdf预览一般不需要前端生成pdf文件&#xff0c;pdf文件一般是通过接口&#xff0c;获取pdf文件【responseType:‘blob’,】或二进制文件流【responseType: ‘arraybuffer’,】或者已有的pdf文件。 前端PDF预览通常是通过读取现有的PDF文件&#xff0c;并使用…

Kotlin return与return@forEachIndexed

Kotlin return与returnforEachIndexed fun main() {val data arrayOf(0, 1, 2, 3, 4)println("a")data.forEachIndexed { index, v ->if (v 2) {//类似while循环中的continue//跳过&#xff0c;继续下一个forEachIndexed迭代returnforEachIndexed}println("…

MATLAB绘制克莱因瓶

MATLAB绘制克莱因瓶 clc;close all;clear all;warning off;% clear all rand(seed, 100); randn(seed, 100); format long g;% Parameters u_range linspace(0, 2*pi, 100); v_range linspace(0, pi, 50); [U, V] meshgrid(u_range, v_range);% Parametric equations for t…