FAQ: Gameplay Networking

Dec 2, 2020.Knowledge

How do we switch from full client prediction to interpolation in order to improve client-side performance?

  • For cheaper simulation of proxies on the client, you can override UCharacterMovementComponent::SimulateMovement() to avoid doing any forward prediction of the capsule location, instead relying on the mesh interpolation between network updates of the capsule location to smooth the visual location. This does imply changes in behavior if you need a smoother capsule location for proxies. Typically, you could choose to interpolate or not based on the distance from the local player if fidelity is an issue. You’ll want to have SmoothClientPosition() always run SmoothClientPosition_Interpolate(), as that is fairly cheap, and only update the transforms and collision with SmoothClientPosition_UpdateVisuals() based on whatever LOD criteria you decide.
  • When you decide to not call the Super implementation that does everything, you still need to do some extra work to handle if you do switch back as well as movement mode changes:

// Copy some Super::SimulateMovement() behavior. if (bNetworkMovementModeChanged) { bNetworkMovementModeChanged = false; ApplyNetworkMovementMode(GetCharacterOwner()->GetReplicatedMovementMode()); } UpdateComponentVelocity(); ClearAccumulatedForces(); bNetworkUpdateReceived = false; bJustTeleported = false; LastUpdateLocation = UpdatedComponent ? UpdatedComponent->GetComponentLocation() : FVector::ZeroVector; LastUpdateRotation = UpdatedComponent ? UpdatedComponent->GetComponentQuat() : FQuat::Identity; LastUpdateVelocity = Velocity;

  • You might still need to call FindFloor if your animations or game code use them, but we try to throttle it down because it can be expensive. You can throttle that over time as well if needed. When switching between non-simulated and fully simulated, you’ll probably need to set bForceNextFloorCheck=true so you don’t use an old floor.
  • For client-side performance, it’s also worth considering whether you need bGenerateOverlapEvents at all on simulated proxies, as the server may just trigger any important events anyway. You might be able to simply disable all bGenerateOverlapEvents flags on everything on the proxy in BeginPlay or PostNetInit on clients, which will further save on movement cost.

How do we set up merging moves so that they are only sent at the framerate of the server, not every client frame?

  • Change these values in DefaultGame.ini as you see fit. They are used by UCharacterMovementComponent::GetClientNetSendDeltaTime() to control the throttling, here is an example:

[/Script/Engine.GameNetworkManager] ClientNetSendMoveDeltaTime=0.05 ClientNetSendMoveDeltaTimeThrottled=0.066 ClientNetSendMoveDeltaTimeStationary=0.0833 ClientNetSendMoveThrottleAtNetSpeed=10000 ClientNetSendMoveThrottleOverPlayerCount=24

What are the best practices for using root motion in networked games?

  • Here is a relevant UDN.
  • Synchronization is heuristical. It depends on the autonomous client playing the same root motion as the server. There is no “start root motion on this character” function, so we don’t have to enforce specific network setups.
  • The idea is that it’s to be used with gameplay abilities, which have built-in networking.
    • Sync is handled by the movement component replication.
    • The gameplay ability system triggers replication, and the movement component does the rest. We’re hoping to make this less confusing in the future.
  • You can run into problems with super short, repeated animations. Paragon aimed for ~1 second animations at minimum, which gives time to synchronize.
  • Network prediction implementation is currently dependent on the gameplay ability system, and is being reimplemented independently.

Does the gameplay ability system (GAS) have a built in mechanism to accommodate high latency with high jitter and packet loss? For example, consider a case where players must wait two seconds after activating ability A to activate ability B. If the first activation is sent with high latency or packet loss occurs but the second is sent with low latency, the server will receive the requests less than two seconds apart, and hence a misprediction could be considered to have occurred and gameplay will suffer accordingly.

  • GAS does have some ability to accommodate poor network connections via client side prediction. In your example, client 1 would predictively activate ability A and send the message to the server. As part of ability A the client will apply a gameplay effect (GE) that puts ability B into cooldown. Due to high latency, the server would get the signal that ability A was activating late but the client would proceed as if things are fine. The server would check if ability A can be activated and inform all clients that client 1 had activated ability A. When client 1 gets this information back from the server it will also include the server’s version of the active gameplay effects which will update the cooldown for ability B on the client to match when the server started ability A.

Does GAS have any built in way to reason the order of events other than order received? For example, if two players with different latencies activate abilities whose order matters, does GAS provide any features to correct the order of these activated abilities, or is it “first message received, first served?”

  • The server is authoritative. Whatever order it receives the ability activations in from the clients is the order that they will have.