[开发者心得] 一些常见的卡顿以及解决办法(创建物体慢、加载动画卡、多端同步慢,卡顿,撕裂)

[复制链接]
1001 |1
剑寂万古 发表于 2023-10-8 11:14:54 | 显示全部楼层 |阅读模式

一些常见的卡顿以及解决办法(创建物体慢、加载动画卡、多端同步慢,卡顿,撕裂)

如果有什么不对的地方请指出来

1. 创建物体慢

在mw(这里指的是口袋方舟编辑器,下同)中,动态的生成一个物体,通常可以使用这行代码 GameObject.asyncSpawn("197386") . 一行代码就能直接调用编辑器来生成一个物体看起来确实很不错, 但是有时候会等待一些时间才会显示出来,或者不能显示出来.

这是为什么呢?在这行代码的运行中发生了什么呢?

我们来分析一下这行代码的执行逻辑

  • 首先mw会先去寻找内存中的资源
  • 在内存中没有找到资源的话要先到资源服务器去下载资源,然后加载到内存中
  • 接着物体会从内存中读取资源数据生成实例
  • 最后将生成的实例渲染到场景中

通过这里分析得到的过程我们可以做出几点优化

  1. 预先下载资源(通过将资源拖入优先加载区域,或者通过资源下载的代码AssetUtil.assetLoaded("197386")AssetUtil.asyncDownloadAsset("197386")预先下载),省去资源下载和资源加载的步骤
  2. 预先生成实例(通过mw提供的GameObjPool或者new ObjPool来生成实例对象池),然后直接修改物体的位置,显隐等方法来控制物体在场景中的渲染

2. 加载动画卡顿

mw中通过Player.localPlayer.character.loadAnimation("4166").play()来给当前客户端的角色加载一段动画

代码执行逻辑:

  • 寻找内存中的资源
  • 没有的话下载服务器资源
  • 然后将动画数据加载给角色

通过这样分析,我们可以看出能做出的优化方案有:

  1. 预先下载资源(mw027之后会有资源自动回收机制,所以这里的高频动画资源需要放到优先加载中去)

3. 多端同步卡顿

在服务器设置一个双端动态物体的位置,客户端在短暂延迟之后也会同样的移动到对应的位置,这就是多端同步,多端同步问题最经常展现出来的问题就是:

  • 明明攻击到了对手,为什么没有扣血
  • 物体存在撕裂,来回拉扯的情况
  • 物体实际的物理位置和显示的不一样(物理效果不同) 在多端同步中,最经常遇到的问题就是网络带来的不确定性 不确定的网络,客户端和服务端帧率不一致都会导致物体的多端同步问题 遇到大规模存在的多端同步问题,就需要就当前的需求进行优化,这里简单的讲几个优化的思路

简单子弹类型(不特别关心过程的同步和改变只关心结果,简单的子弹需求)

在子弹模型中存在大量的子弹,在刚接触的时候我也犯过这种错误,使用双端物体来制作子弹,结果当然是卡的不堪入目,然后经过研究有两种比较好的方法来实现大规模的子弹计算

  • 第一种就是逻辑与表现分离,在这种系统中子弹实际上是分为两部分.服务器逻辑层和客户端表现层.逻辑层实现简单,制作一个简单的碰撞盒代表子弹,然后沿途检测.表现层实现则相比之下比较复杂,接受到子弹发射的消息之后,由特效系统统一实现各种表现效果.同时子弹的伤害效果由技能触发,在子弹击中之后抛出击中事件,从而保证与技能系统具有一致的扩展性.
  • 第二种方法是逻辑和表现都给客户端来管理,服务端收到发射子弹的请求之后分发给所有客户端,然后数据和逻辑都在主控的客户端做出判断,这种方案产生的原因是服务端的内存不够或者运算量不够,但是会方便外挂和修改器的产生.

高频平滑同步(既关心过程又关心结果,比较复杂的同步)

mw本身就有做一部分同步效果,但是这部分效果并不算非常好,针对特殊的需求,需要做到平滑且正确的表现,这时候我们就需要使用特殊的同步方案,目前比较出名的同步方案有两种,帧同步(也叫锁步同步)和状态同步,这里只简单介绍一下这两个方案,如果有兴趣了解,可以去搜索更加详略的文章

  • 状态同步: 对于状态同步而言,简单的说就是当游戏世界中的玩家没有进行操作或者移动的时候,我们认为游戏世界里大家都没有操作,服务器除了一般的心跳检测之类的,不会对客户端下发任何数据进行同步. 当某个客户端进行了某个操作后,操作发送到服务器,服务器将玩家的操作执行出结果,得出玩家现在的快照(位置、血量、蓝量等等变化的信息),再由服务器将该客户端的信息广播下发到其他的客户端进行同步,当然服务器为了防止作弊也是有做验证机制的. 也就是说状态同步就是将逻辑放在了服务器,而客户端更像一个显示器,游戏世界玩家没有属性变化,基本不会进行同步消息下发.
  • 帧同步: 帧同步的概念其实更加简单,每个客户端都在执行相同的操作,所以最后的结果一样. 从上面的话中不难猜出,帧同步的逻辑是放在每一个客户端的,客户端将操作发送给服务器,服务器按照固定的时间内收集操作,然后将这个固定时间内收集的所有操作打包再进行转发给每个客户端后再进行下一次收集,所有客户端再通过服务器下发的操作执行逻辑,就是最初级的帧同步概念,当然服务器也可以执行逻辑进行验证操作防止作弊. 我们所谓的帧理解为一次逻辑的更新时间,就有点类似FixedTime一样,是一个固定的时间. 举个栗子:某者某耀Moba类型游戏,就是15帧的刷新率,也就是它将1秒分成了15次的逻辑更新,你所看见的60-90多帧只是表现帧数,表现帧数越高越丝滑. 还有就是需要使用定点数,当你的逻辑中使用了浮点数的时候,因为每一台机器的不同,浮点最后的有效值其实是不一样的,所以为了保证逻辑的同步性,再游戏逻辑中,需要使用定点数. 大多数帧同步的逻辑是只放在每个客户端的,无论是否有操作,每一帧都会有服务器数据下发.
回复

使用道具 举报

哭唧唧的细狗 发表于 2023-10-8 11:23:45 | 显示全部楼层
好贴
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表