Unity 性能优化二:内存问题

目录

策略导致的内存问题

GFX内存

纹理资源

压缩格式

Mipmap

网格资源

Read/Write

顶点数据

骨骼

静态合批

Shader资源

[Reserved Memory](#Reserved Memory)

RenderTexture

动画资源

音频资源

字体资源

粒子系统资源

Mono堆内存


策略导致的内存问题

  1. Assetbundle 打包的时候,单个资源被重复打包,可以把依赖的资源,单个打包,通过AssetBundleBrowser 可以查看Assetbundle里面的资源情况,地址:Unity Technologies · GitHub

  2. 代码使用不当,资源加载后没有及时销毁,比如:

cs 复制代码
            var gos = Resources.Load<GameObject>("Sphere");
            GameObject go = Instantiate(gos);
            Material ma = go.GetComponent<Renderer>().material;
            ma.color = new Color(1, 0.5f, 0.5f);
            
            //Destroy(ma);
            Destroy(go);

在内存里面还是会存在一份material,因为每次设置color的时候,都是创建了一个新的material

  1. Assetbundle 的卸载不当,导致资源冗余,Unload(false),会把加载的assetbundle 卸载,但从里面加载的资源还在,Unload(true),都会卸载

GFX内存

GFX内存(Graphics)是指图形处理器(GPU)的专用内存,用于存储图形数据和计算所需的临时数据。

纹理资源

压缩格式

  1. 图片在导入unity的时候,会转换成unity识别的的格式,比如jpg,png,这些是在硬盘上存储的格式,但不能不GPU直接读取,所以导入的时候会转换成ETC、ASTC 格式

  2. 图片压缩的好处:

减少占用内存、减少带宽、减少加载时间

  1. 如果图片的压缩格式,在该平台上不支持,会转换成RGBA格式,即不压缩

  2. Android支持ETC/ASTC; IOS 支持 ASTC/PVRTC; PC 支持DTX

  3. ASTC 可以调节压缩块的大小,来调节压缩比例,因为ASTC 是以固定128bit 来存储一个块的,块里面的像素越多,压缩比例就越大,因为平摊到每个像素的存储空间越少,比如4x4,6x6,8x8

Mipmap

  1. mipmap 的好处及坏处

好处:减少带宽 坏处:增加内存

  1. 原理

存储的图片内存是等比数列,1、1/4、1/16......,内存和是原来的4/3倍,也就是内存增加了1/3

  1. 对于2D 界面,因为摄像机距离不会发生变化,所以要关闭mipmap,3D 物体或UI可以根据情况开启Mipmap

  2. 通过Texture Quality 改变加到到内存的Mipmap的数量,从而实现不同性能的机器,配置不一样

通过Edit-Project Settings-Quality--Textures修改,只对开启了Mipmap的纹理生效,里面的FullRes、HalfRes 等内存依次降低为原来的1/4

  1. Texture Streamming 动态改变加载到内存的Mipmap的数量

只对动态加载的Mipmap纹理有效,比如assetbundle加载,如果场景已经存在该纹理,且通过加载场景的方式加载,Texture Streamming则不会生效,因为纹理已经存在了,无法动态改变

纹理加载会根据物体和摄像机的位置,动态实时的去ab包内加载Mipmap

生效条件:纹理开启texture streaming 和 generate Mipmap

MaxLevelReduction(最多裁剪的层级) 的优先级>Memroy Budget (mipmap 占用的最大内存)

网格资源

Read/Write

CPU和CPU会各占一份内存,如果不需要在代码中修改mesh,就不要开启该选项

顶点数据

一份网格的顶点数据有很多,比如position、color、tangent等,但是切线一般是在计算光照的时候才用,可以在导入模型的时候,model 栏下,设置tangent为none,也可以通过projectsetting里面开启optimize mesh data,它会裁剪没有用到的顶点属性,需要测试

骨骼

如果模型不需要骨骼数据,则在模型导入的RIG栏,设置animation type为none

静态合批

会增加内存,空间换时间

Shader资源

  1. shader占用的内存,只要是shader变体,每一个变体都会产生一个shader,加载到内存里面

  2. 游戏初始化的时候一般需要提前把渲染要使用的Shader全部都加载进来,以降低游戏运行时及时加载和编译带来的卡顿,这时候我们可以调用Shader.WarmupAllShaders来把当前已经加载到内存的Shader全部编译一次,包含所有的变体。

  3. 随着项目渲染效果的丰富,Shader变体变得越来越多,粗暴的调用全加载接口,会导致游戏的启动时间变得更长,影响游戏体验。

  4. 后来Unity加入了变体集合ShaderVariantCollection来取代上面的粗暴全加载接口,达到按需加载,提高加载速度

  5. 优化方向:裁剪shader变体

地址:https://answer.uwa4d.com/question/5da86670e84db43d6efbda72

Reserved Memory

RenderTexture

适当关闭抗锯齿,或者降低抗锯齿的质量、减少阴影贴图的质量,即分辨率、降低RT的存储位数(代码生成的时候设置),HDR如果不使用alpha通道的情况,可以修改格式为R11G11B10,即32为存储格式

动画资源

  1. 勾选Resample Code,在模型导入的animation栏中,默认开启,它会减少关键帧的数量

  2. 压缩animation

  3. 骨骼动画,不用scale,剔除不用的scale曲线,通过编辑器代码,AnimationUtility

  4. 降低动画存储的float精度,从而使其存储方式为constant,减少内存

  5. 选中animation,可以在属性面板看到其详细信息

音频资源

  1. ForceToMono:把双声道音频合并成单声道

  2. LoadType:

Decompress On Load:加载后,解压缩,以未压缩的方式存储在内存上

Compress in memory:以压缩方式存储在内存上,播放时解压缩

Stream:边解压缩边播放,但是每播放一次都会增加一份缓存

对于不经常播放的,长而大的背景音乐,用stream,对于短且频繁用第一种(抢声)、其它中等音乐用第二种

3.压缩格式

压缩率越小,压缩后占用的文件内存越小,ADPCM压缩格式,占用内存最小,配合Compress in memory使用

PCM:不压缩、Mp3:次之、Vorbis:更次之、ADPCM:最小

字体资源

  1. 字体瘦身:有些字体不使用,可以裁剪掉,工具推荐:FontSubsetGUI、FontPruner

  2. 字体压缩:TMP 生成的字体问题太大,不能改变,通过提取其纹理,然后压缩,再赋值的方式,压缩纹理

粒子系统资源

  1. 粒子占用的内存和实际播放的粒子数有关,和最大粒子数无关

  2. 如果粒子没播放,也会占用一部分内存,比如:粒子系统只是被关闭了,没删除

Mono堆内存

  1. 常驻内存过高:比如list、dictionary、数组,初始化时的内存不要过高

  2. 持续分配内存:每一万帧,分配不超过50M,通过在初始化时缓存变量

相关推荐
zxc2446039341 小时前
gpu instancer crowd 动画使用方式
unity
C MIKE3 小时前
unity资源下载
unity
Avalon7123 小时前
Unity中自定义协程的实现
游戏·unity·c#·游戏引擎
IMPYLH3 小时前
Lua 的 select 函数
java·开发语言·笔记·后端·junit·游戏引擎·lua
jtymyxmz5 小时前
《Unity shader》10.1.5 菲涅尔反射
unity·游戏引擎
老朱佩琪!5 小时前
Unity文字排版错位问题
经验分享·unity·游戏引擎
jtymyxmz5 小时前
《Unity Shader》9.4.3 使用帧调试器查看阴影绘制过程
unity·游戏引擎
jtymyxmz6 小时前
《Unity Shader》10.3.1 在Unity中实现简单的程序纹理
unity·游戏引擎
jtymyxmz6 小时前
《Unity Shader》11.2.1 序列帧动画
unity·游戏引擎
qq_4286396113 小时前
虚幻基础:虚幻中的if与switch
游戏引擎·虚幻