游戏性能优化总结

性能优化是游戏开发中非常重要的一环,它直接影响到游戏的流畅度和用户体验。我们的游戏基本都是UI为主

UI的一些建议

显示和隐藏我们可以使用移除到Canvas外,而不是利用SetActive(false)

UI的批处理
将更新频率不一样的UI放在不同的canvas上
相同canvas中的UI元素的Z值相同,这样才不会打断合批
相同的canvasUI元素使用相同的材质和纹理,有动态变化不影响合批
相同的canvas中的UI元素要使用相同的裁剪矩阵。
Graphic Paycaster
Text 、spine, image 禁用 caster target

全屏UI的处理
3d场景完全被遮挡,关闭3d场景
被遮挡的UI, disable canvas,不是setActive(false)
尽可能降低帧率,UI不需要刷新那么频繁。

其他的一些优化

Gameobject 层级结构
某些情况下,场景中的物体坑有很深的嵌套结构,
对父节点的Gameobject 移动,会产生OnTransformCHanged 会传递给子对象,所有子对象
即使没有渲染组件的,会造成一些不必要的转换运算。
较深的结构也会导致GC更耗时,

避免在awake 和 start 中添加大量的逻辑,游戏启动黑屏太久。因为游戏是在、Start 方法后执行渲染第一个画面

删除空的unity 事件,Awake() Start() Update
即使是空的也会带来微性能消耗

accelerometer Frequency
Project setting - player -ios - other settings ,不需要加速仪的游戏中,关闭,或者设置低频。会增加cpu负担。

移动物体,
如果对象需要碰撞检测,不用tranform。Translate, 用rigidBody.MovePosition, addForce 并且是在fixedupdate 方法中执行。

添加组件
在运行时调用AddComponet其实很没有效率,尤其是一帧中多次启用这类调用
当我们添加一个组件的时候,
影响性能,增加GC的处理时间

数据结构,array,list 和dictionary
array list使用索引成本低,适合要经常通过索引读取的情况,而频繁增加和移除对象,使用dictionary

audio的优化

project settings
DSF buffer:FMOD声音引擎有个buff,就是DSF buffer,当buff满了才会去向CPU发送一次播放声音的指令。Default、Best Latency,Good latency, Best performance

audio source
Force To Mono:强制单声道
Compression:Android: Vorbis 、IOS:ADPCM、MP3
LoadType:Decompress OnLoad 必须<200k Complress In memory 中型音频文件,streaming,大型,背景音
Bitrate 减低文件的比特率,前提是不会破坏太严重。

静音处理:disable audiosource组件,建议在内存中卸载音频相关的来源

Code size;代码也占内存,模版泛型的滥用。

assetbundle ,typeTree,不同版本数据结构的兼容,TypeTree build 的版本没有升级,关闭它
BuildAssetBundle.option.DisableWriteTypeTree

压缩方式 lz4, chunkBasedCompression。
大小和数量 ;官方建议是一个1-2m,现在是5g时间可以适当加大,

禁用Resources

Texture
Project setting
Async Upload Buffsize 16

Read/Write 关闭,不然会出现两份(内存和显存都在内存)
mipmap, ui 元素禁用
format ASTC
alpha 对完全不透明的纹理 关闭alpha通道

max size 设置成该平台最小值
合并,尽量多张纹理合并成大图

mesh 网格
read/write 关闭
compression 关闭(有些版本卡了,解压后内存占用会很大)
Rig 没有动画的比如静态的房子,石头 关闭
Blend shapes 没有用的的也禁用
met额日阿里 没有用的法向量和切线,也可以关闭。

优化managed memory

游戏对象,显示的调用Destroy 不要用null,销毁不完全。

Class 和 Struct 根据具体使用情况选择class 或struct
减少装箱拆箱操作
减少LINQ表达式,String。Fromat()

对象池
创建和销毁游戏对象很常见,频繁创建和销毁GC会导致负载很重而波动
还会导致堆内存碎片化。对象池大小要合适。

闭包和匿名函数( 在编译成IL代码中会被new成匿名类。
所有函数,变量,以及new出来的东西都要占用内存。

协程
协程属于闭包和匿名函数的特例,建议new的时候生存一个协程,不用的时候丢掉

配置表
分关卡加载配置。

慎用单例,不要什么都往里放,变量会一直占用内存。

scriptable object ,只会消耗一组数据内存。

变量Or 属性
属性本质上是函数的调用,会在堆栈上被分配内存,调用属性也是如此,当然一般来说问题不大,
可以用宏命令,开发时使用属性,发布时使用变量。

缓存hash值
int h = Animator.StringToHash(“idle”)
animation:SetTrigger(h)

int s = Shader.PropertyToID(“color”)
material.SetColor(s,Color.white)

缓存引用对象
不要多次查询相同的对象或组件,查询一次后将其缓存起来,
方便后续使用。

图像(Graphics) 的一些优化建议
使用批处理来尽量减少draw call。
静态批处理满足:要合批的对象必须引用一样的材质,并使用相同的纹理(纹理合并在这里就体现出来了),使用的模型可以不一样。

动态批处理: 减少移动对象的drawcall,只能用于少用900个顶点的信息。包含坐标,法线,uv0,uv1,q切线,每帧评估一次,cpu处理

castShadows
meshRender 组件的Cast Shadow 开启阴影渲染,增加真实度和深度感,增加多余的阴影计算,最后看不见。如果对阴影没影响,可以关闭。

light Culling mask 分层,确保只影响特定层( 专门给角色打光的光源,设置成只影响角色)。尤其是多光源,多对象。

避免使用手机原生分辨率
现代手机分辨率很高,在手机上程序影响性能和手机过热
使用Screen。SetResolution来降低游戏预设的解析设置,来提高性能。