当前位置:   article > 正文

Unity 优化

unity 优化

Unity 优化

最近阅读了Unity 游戏优化 第三版,里边确实有些东西开阔了视野,让我更加理解了一些Unity的相关知识,也做了一个大概的提示记录。相当于一个提示,提醒我有哪些方面的优化,能从哪个角度入手。
一、脚本优化
1.使用最快的方法获取组件
(1)GetComponent(string);最慢
(2)GetComponent();最快
(3)GEtcomponent(typeof(class));与(2)差不多
2.移除空的回调,Awake、Start、Update等Monobehavior周期函数
3.缓存组件引用,不要每次都去获取Get、或者Find
4.Update、Coroutines、InvokeRepeating
(1)Update计时等可以使用Coroutines替代,减少无用调用
(2)WaitForSeconds或者WaitForSecondsRealtime调用yield可以替换成InvokeRepeating
(3)但是InvokeRepeating完全独立于MonoBehaviour和GameObject的状态,禁用MonoBehaviour或GameObject都不会停止InvokeRepeating,使用CancelInvoeke或者删除GameObject或者MonoBehaviour才行
5.GameObject空引用检查,避免本地-托管桥接 包括避免gameobject.name/tag ==str 这种写法
6.避免运行时修改Transform父节点,关注Transform的变化,节点不要太深
7.避免使用Find()或者SendMassage
(1)合理将引用分配给预先存在的对象
(2)静态类
(3)单例
(4)信息传递
8.禁用不使用的脚本和对象
(1)可见性禁用
(2)距离禁用,尽量不使用开平方根的算法
9.最小序列化行为
10.叠加、异步加载场景
11.创建自己的Update层
二、图形优化
1.批处理
(1)DrawCall
①从CPU发送到GPU用于绘制对象的请求,或者可以理解为初始化当前渲染过程之前的配置选项。
1)上传资源网格到GPU
2)使用上传的资源设置网格的渲染
②CPU必须配置处理对象所需的选项和渲染特性,为GPU做好准备
③渲染状态:在渲染对象之前,为准备管线渲染而配置的大量设置常常统称为渲染状态。更改渲染状态是一个耗时的过程。
④批处理提升此过程的诀窍在于,新的DrawCall不一定意味着必须配置新的渲染状态,如果两个对象共享完全相同的渲染状态信息,那么GPU可以立刻开始渲染新对象,因为在最后一个对象完成渲染之后,还维护着相同的渲染状态,这消除了由于同步渲染状态而浪费的时间,也减少了需要推入CommandBuffer中的指令数,减少了CPU和GPU的工作负载。
(2)材质和着色器
①渲染状态本质上是通过材质呈现给开发者的,材质是着色器的容器。
(3)FrameDebugger
(4)动态批处理
①所有网格实例必须使用相同的材质引用
②只有ParticleSystem和MeshRenderer组件进行动态批处理,SkinnedMeshRenderer组件和所有其他可渲染的组件类型不能进行批处理
③每个网格之多有300个顶点,但是着色器使用的顶点属性数不能大于900。这意味着对于复杂的着色器,每个网格的最大顶点数可能小于300
④对象不能在变换中包含镜像(也就是说,一个具有正比例的游戏对象A和一个具有负比例的游戏对象B不能放在一起批处理(XYZ奇数负比例))
⑤网格实例应该引用相同的光照纹理文件
⑥材质的着色器不能依赖多个过程
⑦网格实例不能接受实时投影
⑧整个批处理中网格索引的总数有上限,这与所用的GraphicsAPI和平台有关,一般索引值为32~64K
(5)静态批处理
①网格必须标记为Static
②每个被静态批处理的网格都需要额外的内存
③合并到静态批处理中的顶点数量是有上限的,这与所用的GraphicsAPI和平台有关,一般为32~64K个顶点
④网格数据可以来自任何网格数据源,但是必须使用相同的材质引用
2.优化艺术资源
(1)音频文件
①产生音频瓶颈的原因有多种多样。过度压缩、过多的音频操作、过多的活动音频组件、低效的内存存储方法和访问速度都会导致内存和CPU性能低下。
②导入设置
1)加载行为
2)压缩行为
3)质量
4)采样率
5)是否支持双声道等
③加载音频
1)PreLoadAudioData
2)LoadInBackground
3)LoadType
a.DeCompressOnLoad,压缩磁盘上的文件以节省空间,在首次加载时将其解压到内存中。
b.CompressedInMemory,在加载音频时只是将其从磁盘复制到内存中。只有在播放音频文件时,才会在运行期间对其进行解压缩。此设置是和频繁使用的大型音频文件,或者在内存消耗上遇到瓶颈,并且愿意牺牲一些CPU周期来播放音频剪辑。
c.Streaming,将在运行时加载、解码和播放文件。特定音频剪辑使用的内存两最小, 运行时CPU使用的内存最大。
④编码格式和品质级别
1)品质
a.Compressed、Vorbis等,适合中等长度
b.PCM,最好,比较小的文件适合
c.ADPCM最差,通常一些爆炸、脚步声,武器声等
2)音频格式
a.Wav,windows开发的一种音频格式,简单的编码/解码、普遍的认同/支持以及无损耗存储,Windows上最流行的文件格式。
b.Ogg,一种有损压缩音频格式,和Mp3类似,没有专利限制
c.Mp3,一种有损压缩音频格式,大小只有wav的1/10。
d.Aif,苹果开发的一种音频格式
⑤音频性能
1)最小化活动音源
2)为3D声音启用单声道
3)重新采样到较低的频率
4)考虑所有压缩格式
5)注意流媒体
(2)纹理文件
①纹理和精灵
1)纹理:简单的图像文件、一个颜色数据的大列表
2)精灵:网格的2D等价物,定义了图像在游戏中出现的方式和位置
②压缩格式
1)None、LowQuality、NormalQuality、HighQuality
③性能增强
1)减小纹理文件的大小
给定的纹理文件越大,推送纹理所消耗的GPU内存的带宽就越多
2)谨慎使用MipMap,内存增加33%。
3)从外部进行分辨率的压缩管理
4)考虑使用图集
5)调整非方形纹理的压缩率
a.纹理文件通常以正方形、2的n次幂的格式保存,这意味着他们的宽度和高度相等,而大小是2的n次幂。128x128、256x256等
b.也可能出现长方形纹理,256x512等,一些GPU需要方形纹理格式,因此Unity将自动拓展长方形纹理到额外的空白处进行补偿,以适应GPU期望的格式,这将消耗额外的带宽。
(3)网格和动画文件
①减少多边形数量
②调整网格压缩
③恰当使用Reas-Write Enabled
④考虑烘焙动画
⑤合并网格
(4)AssetBundle和Resources
①Resources
1)可伸缩性不大,所有文件合并到一个大型序列化文件二进制数据blob中,其中包含一个索引列表。
2)Resources系统以Nlog(N)的方式从序列化文件中获取数据,所以要警惕N的值。
3)Resources系统难以为不同平台提供不同数据
4)必须完全替换应用程序才能进行内容更新
②AssetBundle
1)可用于为应用程序提供小型的、定期的自定义内容更新
2)但是建立和维护更复杂
3.加速物理引擎
(1)物理引擎如何工作:时间步长和FixedUpdate、碰撞器类型、碰撞、射线发射、刚体激活状态
①用于3D的Nvidia的PhysX和用于2D物理的开源项目Box2D
②物理和时间
1)通常假设在固定时间值运行,每个迭代称为时间步长
2)最大允许的时间步长。如果自上次固定更新以来已经过了很长时间,那么固定更新将继续在相同的固定更新循环中计算,直到物理引擎赶上当前时间
3)物理更新和运行时变化:比如,在Update中施加力,会导致两个不同的设备之间的合成速度完全不同于在固定更新中执行相同的操作。从逻辑上讲,在任何给定的固定更新迭代中花费的时间越多,在下一次游戏逻辑和渲染过程中花费的时间就越少。
4)静态碰撞器和动态碰撞器:是否有Rigdbody
5)碰撞检测,离散、连续、连续动态
6)碰撞器类型
a.性能成本从小到大:球体、胶囊体、立方体、网格
7)碰撞矩阵
8)Rigidbody激活和休眠状态
9)射线和对象投射
10)调试物理
(2)物理性能优化:如何构造场景以优化物理行为,使用相应的碰撞器类型,优化碰撞矩阵,提升物理一致性并避免容易出错的行为,布娃娃和其他基于关节的对象。
①场景设置
1)缩放:尽可能(1,1,1)比例
2)位置:尽可能接近(0,0,0)
3)质量
②适当使用静态碰撞器
③恰当使用触发体积(Trigger)
④优化碰撞矩阵
⑤首选离散碰撞检测
⑥修改固定更新频率
⑦调整允许的最大时间步长
⑧最小化射线投射和边界体积检查
⑨避免复杂的网格碰撞器
⑩避免复杂的物理组件
⑪使物理对象休眠
⑫修改处理器迭代次数
⑬优化布娃娃
⑭确定何时使用物理
4.动态图形(图形渲染还是弱项,不怎么会)
(1)渲染管线
①CPU通过图形API向GPU设备发送渲染指令,再通过硬件驱动程序发送给GPU设备,渲染指令列表会累积在一个称为“命令缓冲区”的队列中。这些命令由GPU逐一处理,直到命令缓冲区为空。只要GPU能在下一帧开始之前跟上指令的速度和复杂度,帧速率就保持不变,然而如果GPU跟不上,或者CPU花费太多时间生成命令,帧速率将开始下降。
②GPU前端:渲染过程中GPU处理顶点数据的部分
③GPU后端:渲染管线处理片元的部分
1)填充率
2)内存宽带
④ 光照和阴影
1)前向
2)延迟渲染
(2) 性能检测
(3)渲染性能增强
①启用/禁用GPU Skinning:Skinning是基于动画骨骼的当前位置变换网格顶点的过程。
②降低几何复杂度
1)美术团队手动调整
2)简单从场景中移除网格
3)网格自动剔除(如LOD)
③减少细面曲分
④GPU 实例化
⑤LOD
⑥遮挡剔除
⑦优化粒子系统
⑧优化UI
⑨减少纹理数据
三、高级优化
1.虚拟现实和增强现实优化
2.内存管理
(1) Mono平台
①与Unity配合使用,使Unity具有很多跨平台功能。
②内存域
1)托管域
2)本地域
3)外部库
③栈
1)栈是内存中预留的特殊空间,专门用于存储小的、短期的数据值
2)栈包含了已经声明的任何本地变量,并在调用函数时处理他们的加载和卸载
3)之前内存分配的开始位置总是已知的,没有理由执行内存清理操作,因为内存分配只会覆盖旧数据。因此,栈相对快速、高效
4)栈的容量通常很小,大约为兆字节。当分配超过栈可支持的空间时,可能会导致栈溢出,这会出现在执行大量调用栈时或有大量本地变量时,但大多数时候,尽管栈的容量相对较少,但很少会引起栈溢出
④堆
1)堆表示所有其他的内存空间,并用于大多数内存分配
2)由于我们想让大多数内存分配的持有时间比当前函数调用更长,因此不能在栈上分配他们,因为他们会在当前函数调用时被覆盖
3)在物理上,栈和堆都没有什么不同,他们都只是内存空间,包含存在于RAM中的数据字节,操作系统会请求并保存这些数据字节,不同之处在于使用他们的时机、场合和方式
⑤垃圾回收
(2)代码编译
①AOT
②JIT
③完全静态
(3)IL2CPP
(4)内存管理性能
①垃圾回收策略:最小化垃圾回收,在合适的时间手动触发垃圾回收器
②值类型和引用类型
③字符串连接
1)StringBuilder
2)字符串格式化
④对字典键使用InstanceID,要缓存
⑤对象池、预制池
3.面向数据的技术栈
(1) 作业系统
①多线程问题
②Unity 作业系统:JobSystem
(2)ECS
(3)Burst编译器
4.使用GPU Instancing优化大量动画对象

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/897999
推荐阅读
相关标签
  

闽ICP备14008679号