UE 高Ping状态模拟

  • Config/DefaultEngine.ini中添加设置如下内容
    1
    2
    [PacketSimulationSettings]
    PktLag = 100

    客户端预测算法产生的核心问题

  • 客户端先去执行,服务器用于验证客户端执行的代码是否正确,由于通信的延迟问题,服务器不能强行将客户端强行拉回当前位置,会出现瞬移卡顿的问题。
  • 玩家射击过程中,武器特效”不跟手“(即需要进行两次服务器RTT之后才能获取到特效以及子弹发射等,如果网不好会很卡的问题)。

武器特效不跟手的问题

在文章《散弹枪思路——服务器客户端随机数同步》中有写到,

角色移动部分的算法总结

  • 思路:就是客户端根据RTT时间预测提前发送给服务器收到时预测客户端落点数据。流程:
    1. 客户端移动。
    2. 客户端将数据通过RPC发送给服务器,并保存下来。
    3. 收到从服务器的回复。
    4. 验证服务器当前的数据是否对应客户端。
    5. 丢弃 旧的 从服务器接收的回复。
    6. 重新在客户端应用服务器还未处理的移动。

弹药计算部分的算法总结

  • 核心:客户端提前执行,服务器端验证逻辑
    • 验证成功,客户端不变;
    • 验证失败,客户端更改;(PS:一般不会验证失败,除非被外挂之类的修改了)。
  • 开火时失去弹药的流程:
    • 1、服务器执行多播将Fire函数在所有客户端以及服务器中执行。
      • 其中,所属Client与Server都调用SpendRound函数进行弹药计算。
    • 2_Client、执行SpendRound函数在客户端本地调用设置Ammo以及对应的HUD,并通过 Sequence 变量存储用于验证。
    • 2_Server、SpendRound()在服务器调用时执行ClientUpdateAmmo客户端RPC函数对客户端提前的内容进行验证,验证函数流程ClientUpdateAmmo_Implementation:
      • (1)、获取到当前的服务器发送并客户端收到的弹药数量,赋值到客户端Ammo中(因为以服务器作为权威)
      • (2)、由于已经收到一个回传的包,一次开火已经验证完毕,因此 Sequence 减一
      • (3)、Ammo 在减去正在验证的服务器 Sequence 数量。
  • 加入算法后的重新换弹的流程,还是核心不变:
    • 1、服务器以及客户端调用UCombatComponent::HandleReload(),播放Montage
      • 播放后,Montage调用UCombatComponent::FinishReloading()
      • FinishReloading函数调用UCombatComponent::UpdateAmmoValues()处理主要换弹的逻辑
      • UpdateAmmoValues函数调用AWeapon::AddAmmo进行子弹的更换
    • 2、AWeapon::AddAmmo服务器调用AWeapon::ClientAddAmmo_Implementation进行换弹逻辑。