游戏卡顿问题处理与相关算法解析

棋牌游戏开发 10个月前 159浏览 0评论

1.处理卡死问题

1.如果是玩家触发卡顿,先上传玩家的日志,查看其帧率,然后定位到帧率低的时间,以及玩家进行了哪些操作。

2. 如果可以重现卡顿,则运行profile(用于记录一帧内所有函数的执行时间),重现卡顿,然后根据profile结果进行分析。

3.如果帧率没有突然变化,而是一直保持在较低水平,首先判断是否是定时器使用不当。

4. 如果最近才出现滞后,并且之前没有滞后,您可以检查 SVN 记录以查看最近的更改。

2.游戏相关算法

1.分离轴算法:用来实现多边形碰撞检测(引擎自身的碰撞检测效率较低,移动速度过快的物体会穿透)

2、碰撞检测将物体分成N叉树:一个场景中碰撞体非常多,但是不可能对所有物体都进行碰撞检测,因此需要将场景中的物体分成N叉树,以减少碰撞检测的次数。

3、基于有符号距离场(SDF)的地图碰撞系统:类似王者荣耀中物理移动效果的实现。一般开发时不会用到Unity自带的物理碰撞系统(因为不可控,效率低)。

4.两遍跳到最大连通面积算法:一般用在随机生成迷宫的游戏中,迷宫中会有障碍物,为了防止玩家卡在被阻挡的位置,需要用到这个算法,让玩家可以跳到最大连通面积。

5、时间轮算法:一般用于定时器的实现,我们每次新建一个定时器,都需要把它放到一个列表中,然后计算每帧需要执行哪些定时器,如果通过遍历所有定时器来确认需要执行哪些定时器游戏开发,效率太低了,使用时间轮算法,不用遍历定时器就可以知道需要执行哪些定时器。

6、A*寻路算法:自动寻路AI,主角寻找通往NPC路径的必备算法。

7.射线检测算法:用于射击游戏,某些碰撞检测,各种图形算法等。

3. 游戏相关性能优化的常用方法

1.空闲加载(异步加载):当一帧中的逻辑过多时,将一些可以延迟的逻辑放到空闲帧中,避免卡顿。

2. 场景分块加载:对于大型场景,进入游戏时并不会加载整个场景中的所有物体,而是根据玩家当前位置选择附近的物体进行加载。

3、遮挡剔除:当多个物体重叠在一起时,玩家其实只能看到最前面的物体,后面被遮挡的物体是看不到的,此时可以将被遮挡的物体剔除,以提高运行效率。

4、协议管理:管理服务器返回的协议,对于不需要立即执行的协议,可以使用空闲加载的方式执行(如果处理不好,容易出现各种bug)。

5. 合并与批处理:如果一个界面上有多张图片,我们一张一张的读取,CPU 和 GPU 会交互很多次。但是如果我们将多张图片合并为一张,CPU 和 GPU 只需要交互一次(当然也可能不是一次,主要取决于合并后的图片是否包含所有图片),就可以读取所有图片。同样,对 3D 模型网格进行批处理也是同样如此。

6、对象池:每次实例化对象都会有较大的消耗,所以需要一个对象池。对于重复创建的对象,销毁的时候并不是真正销毁(只是对象被隐藏了)而是放入池中,再次需要的时候直接从池中获取。

7.多路复用滚动框:一般我们看到的滚动框都是多路复用滚动框,也就是说滚动框里的项目数其实只有我们看到的数量,而不是有多少个项目就有多少个条目。

8. 预加载:有些资源可能需要较长时间加载,触发时可能会造成卡顿(比如一个华丽的技能,发布时加载很多功能可能会造成卡顿),这种情况下可以提前加载,然后隐藏,需要的时候直接显示。

9. GPU Instancing:对于同一个 mesh,如果要渲染 10000 个 mesh,就需要向 GPU 传输 10000 次数据。如果使用 batching,只需要传输一次数据,但传输的数据量不变,还是 10000 条数据。但这 10000 条数据是相同的,所以你可以向 GPU 传输 1 条数据,然后 GPU 就可以直接渲染 10000 个 mesh。

4. 内存优化方法

1. 当触发内存警告时,会自动清理部分资源缓存。(主要是纹理,也就是图片)

2. 当资源引用为0时,立即清理该资源。(但这个资源可能很快又会被用到,所以需要根据情况选择处理方式)

3.尽量减少颗粒数量。

5. 调试方法

1、如果进入游戏出现黑屏,请检查本地日志文件。

2.iOS可以通过爱思软件查看日志文件。

3.Android可以直接连接adb查看游戏实时日志。

4.本地调试真实机器代码时,可以直接使用热替换进行调试。(因为每次改代码都要打包或者打补丁,耗时太长,所以热替换调试比较快)

5.对于收到补丁代码前(补丁代码由服务器发送,这里指的是服务器发送补丁代码之前)的调试,可以默认读取一份本地的代码文本,进入游戏时直接执行。

6. Shader 执行时无法打印,如果想查看数据,可以使用 Intel gpa。

6. 调试技巧

1.最直接的方式就是在这里打印某个函数是否被调用,以及执行时的值。

2. 定位某个函数的代码,可以先触发该函数,然后看打印了哪些内容,再通过控制台回溯,定位到该函数触发时的相关代码走向。(类似断点,但是断点会冻结进程,并且执行完下一个断点后,无法跳回上一个断点查看)

3.对于没有打印的函数,应该先联想到最终结果涉及的一些函数。比如我不知道NPC行走函数在哪里,但我知道最终结果是NPC行走,也就是说SetPos函数肯定会在NPC身上执行。那么我可以重写它的SetPos函数,并添加打印,然后我就可以通过控制台来查看NPC行走是如何执行的。

4.当定位到某些界面的代码位置时,可以直接ctrl+左键点击界面,就可以跳转到界面对应的代码。(这个功能是我自己实现的,其实只要监听点击,获取点击的界面对象,就可以得到这个对象的类,然后直接跳转到ide就可以了)

5、如果打印的数据太多,但只想分析一个对象,可以设置只打印与该对象匹配的数据。

6. 你可以在打印件上添加更显眼的字母,以便我们更容易找到自己的打印件。(你可以使用控制台进行筛选)

七、其他问题

1.iOS无故杀死进程,一般是因为游戏内存占用过高。

2.PC上没问题,但真机上有问题,可以检查补丁是否包含修改内容,逻辑是否有环境判断。

3、Android没问题,iOS有问题(或者Android有问题,iOS没问题),这个一般是资源问题导致的,需要检查各个平台读取的资源是否一致,同时检查云效自动生成的资源是否有问题。

4、在不稳定功能上线时,可以选择随机概率做灰度测试,这样即使出现问题,玩家只要重新登录,也有一定的几率切换回正常。

5. 发现作弊行为后,不应立即封号游戏开发,而应等几天再封号,给作弊者调试带来不便。

6、第一次打开界面时,某张图片不出现,第二次打开时,正常出现,这种情况一般是异步加载导致的,异步加载资源加载完成后没有设置回或者加载完成之前调用了设置函数。

7.接口打开后无法关闭,这个一般是接口引用有问题,没有将引用返回为0导致的。

8、游戏内存占用很高,一般是某些资源循环引用或者引擎打印大量错误提示导致的。

9. GPU Instancing 要求相同的 mesh,相当于多次渲染时把相同的 mesh 数据交给 GPU 处理。Batching 不要求相同的 mesh,它会把所有 mesh 数据聚合起来,一次性发送给 GPU 进行渲染。

分享:

支付宝

微信