移动游戏性能优化通用技法

发布于:2025-07-19 ⋅ 阅读:(31) ⋅ 点赞:(0)

前言:

优化的目标:

1.降低电池损耗。

2.游戏能够平稳运行,在核心游玩期间无剧烈卡顿现象。

3.合理的内存的使用。

4.降低CPU上的压力。

5.降低GPU上的压力。

6.降低网络带宽上的压力。

7.降低包体大小

下列优化项,除了文章以外,还有一些个人理解,如有错误,欢迎提出改正

1. 资源优化

纹理部分:控制在2的N次方,方便真机压缩(android的ETC,ios的ASTC)。尺寸不要太大,最大1024x1024足够。辅助纹理,如遮罩图只留个单通道就够了。提高纹理使用率,如9宫格,UI图集。

UI层次:对于相同图集的UI层级相邻近一些,方便合批。把UI分成动态和静态二部分,降级ReBatch,Rebuild的情况。频繁显隐的UI,不显示的时候挪到相机看不到的地方,降低Rebuild。

字体:对于不用的字体,如阿拉伯文,泰文,可以从字体资源里摘除从而降低字体资源的大小。

模型:控制场景和人物的顶点数和面片数,主要人物顶点可以多一些,次要的就要少。

粒子:尽量少用,会增加DrawCall和OverDraw的次数

音频视频:音频视频文件大小需要控制,背景音乐可以大一点,音效需要小。

2. CPU优化

算法优化:比如使用快速排序代替冒泡排序,使用JPS寻路代替A*寻路,简单的战斗碰撞使用AABB进行模拟。

利用CPU的三级缓存:如简单数据使用struct而不是class。对于海量的单位可考虑使用Unity的Dots。

减少与lua的通信:如使用xlua进行开发,如设置坐标。可以在C#中写一个类似Tool.SetPosition(GameObject go,float x,float y,float z)这样的方法。明显通信效率要高于a.transform.position = CS.UnityEngine.Vector3(x,y,z)

主次法:主要的逻辑可每帧调用,次要的逻辑可每过几帧调用。

动画:降低动画采样率,减少关键帧数据,使用简单插值代替复杂插值

物理:降低射线使用,禁用复杂碰撞改用简单碰撞。

粒子:考虑是否可用缓存/预加载/预计算的优化方式。对特效的重要程度分级,不重要的粒子不计算或者降频。

减少耗时函数的调用:如查找DNS地址不要每帧都调。

3. 渲染优化

减少DrawCall:如看不见的UI,只渲染这个UI的相机可以关闭。看不见的模型隐藏掉。使用SPR Batch来减少SetPass Call。UI使用UI图集非每个资源都要使用单图。

使用合批:对于场景固定建筑模型使用静态批处理,对于动态建筑使用动态批处理,但对其材质有shader要求。

开启背面裁剪:看不到的物体,可以cull back

使用GPU Instance:对于使用相同Mesh和材质的模型,可以使用该技术。

减少Alpha Test和discard的使用:会破坏early-Z。

减少灯光的使用:游戏一般一个主光源就够了。多光源会加剧GPU运算压力,虽然延迟渲染可缓解该压力,但对于透明物体支持不太好。

控制Render Queue:对于使用Alpha Test等破坏early-Z的物体,可以先于透明物体渲染。

Shader少用逻辑判断:if else 会产生分支,导致GPU的性能下降。可以使用step等平替

Shader计算尽可能在Vertex Shader执行:如果在Fragment Shader中执行,计算压力会变大很多。像素远超顶点数目。

改用阴影图代替ShaderMap:阴影图的生成是放在光源上先生成一张深度图,然后再从相机视角得到的一张图映射到光源视角得到深度图,然后二者比较深度而来。性能肯定比不了直接挂在模型下的阴影图。

使用LOD分级:远的使用低模,低分辨率贴图,近处使用高模,高分辨率贴图。

简单模型动画可使用换mesh的方式来实现非骨骼动画:因为骨骼动画无法合批,而Mesh可以进行动态合批。

少用抗锯齿:因为抗锯齿需要高分辨率的渲染缓冲区,并且频繁读写。增加了显存带宽。

降低画面质量:对于低端机可使用低分辨率的渲染,高端机高分辨率。如高分辨率2540x1080,低分辨率1470x540。

4. 内存优化

缓存法:可以将需要重复使用的数据或模型等缓存起来。如对象池,内存池

减少对象的创建:如C#使用stringBuilding拼接字符串,比如string + string 创建对象更少。

合理GC:比如在Loading的时候及时GC,腾出更多的空间。

逻辑优化:如使用非托管堆内存如C#的struct,及时释放,不要不用的时候只是野掉。

5. 卡顿优化

限帧法:可以设置引擎固定刷新频率。

分帧法:某些大的耗时功能可能分成几帧或者使用个协程来执行。

多线程法:某些不影响主逻辑的功能,比如获取DNS地址非常耗时,可以另开个线程来执行。

限制数量:离玩家视角较远的模型隐藏,近的才会显示。限制同屏最大人物数等。大世界做的分块加载等。

预加载:提前把一些重要模型或特效在loading条时,加载进来。减少卡顿。

IO读取:尽可能减少运行游玩时的IO读取,会造成明显卡顿。使用JSON比使用XML性能更好,使用纯bytes文件性能比Json好。

减少GC次数:以Unity为例,不要在Update里每帧都去创建大量的非托管对象。

6. 网络优化

减少无用字段:朝向只在xz平面上,所以只需要发送RotationY。

网络异步化:开辟独立的线程处理收发网络协议包,是游戏常见的优化手段,可以避免与主线程相互等待。

高效使用字节:如一个Int为32位,可以让其前8位代表人物状态,次8位代表人物血量,中8位代表人物攻击力,末8位为人物防御力等。

压缩协议包:游戏最常用的压缩方法是zlib开源库,还可以用lz4方法。

使用合适的协议:如不使用TCP,改用Udp,或者KCP提高效率。

降低网络通信:如客户端本地设置个发某个协议版本号,只有版本号出现变化的时候才会跟服务器拉取最新数据。而不是每次都要拉取。

7. 其他

机型分级:某些特效在高端机可以全播全,在低端机就播不全。对于游戏性不是那么敏感的游戏,可以高端机可以使用高帧率,低端机不让其使用高帧率。

使用功能包或者CDN下载:把必要的资源放到包内,其他玩法上的功能或者资源可以在游戏运行时,边玩边下载。


网站公告

今日签到

点亮在社区的每一天
去签到