Mover and GAS

I’m trying to figure out how to make Gameplay Attributes and Gameplay Abilities work with Mover and its resimulation/replication. The examples aren’t clear.

Our game has a character dash - basic effect is push a button, character receives a boost (constant linear velocity applied over time for a specific duration.) Current implementation is using FLayeredMove_LinearVelocity and works fine.

Details: The dash input button fires a dash gameplay ability, that gameplay ability checks to make sure the player has enough stamina (a gameplay attribute) then sets properties in our custom mover component. Then ProduceInput consumes those properties and sets other properties in a custom struct that hangs off the input collection (FMyAdditionalInputs that works like the FCharacterDefaultInputs of the examples.) OnMoverPreSimulationTick then processes that struct and actually creates the layered move. For this to work well, the gameplay ability can be local only, and all NPP related rollback is isolated entirely to the mover simulation.

My first question is: can abilities cause a rollback? In the above example, say player A has enough stamina locally and presses dash, but then gets notification of another ability from player B that burns their stamina below the required level. Will NPP rollback my gameplay sim to play that ability, and if so will it replay my execution of dash and have it fail? If _that_ happens, will it know it needs to rewind the created layered move as well?

My second question is about the mover sim existing on both client and server. Imagine player B has an ability (call it pull) that does a linear velocity layer move on player A? There’s three different places simulating both ability and movement in this case, and I want to understand how they interact.

One potential guess is that a LocalPredicted version of pull would generate layered moves for player A on player B’s client, but that when the server also activates the ability it can make authoritative versions of the layered moves for player A - how are those resolved on player B’s client? It doesn’t seem like there is sufficient information for player B’s client to know that the interpolated information it receives from the server it has already generated locally because nothing associates the moves with the abilities, so is a correction just inevitable then? What about the case where the movement and the gameplay activations are interleaved? Will NPP rolling back in time for one force rollback/resim for both?

I understand that “more work needs to be done to show how Mover and GAS should work together” and that’s coming post-5.7 from reading other questions, but what I’m mostly looking for is some kind of high level guidance about how much information I need to supply to the movement for resimulation. At a high level:

  1. Is Mover just interpolating values and first derivates its receiving from a server tick, or is it replaying pieces of the movement stream?
  2. What’s the difference between “Forward Predict” and “Interpolated” for Simulated Proxies?
  3. What are the ramifications of turning my simulation tick way, way down? It seemed at first blush that Mover might be forwarding around the actual input events and then doing resim/rollback on mispredict but from other people’s questions here that might not be the case?
  4. Are these actually all the same question? :wink:

Steps to Reproduce
Mover and GAS simulation resolution questions

Taking questions down the line:

  • Abilities can’t trigger rollbacks, at least not directly. In your case, the client predicts the dash layered move but the server did not. You’ll get a movement correction, and hopefully the stamina value has replicated via GAS by then as well. Allowing external systems to trigger client-side rollbacks is something we’ve discussed, but haven’t tackled. Long term, abilities would be plugged into the same underlying simulation timeline and be able to cause corrections and rollback in tandem with movement. Depending on your game, you may consider trusting the client by including additional information about what it thinks the stamina to be at time of activating the dash. If the server thinks it’s within reason, allow the action.
  • During resimulation, it starts from the latest authoritative state received from the server, then replays moves using the inputs it previously authored.
  • Interpolated: SP are interpolating their state towards the most-recently received server-authored state. Simulation is not occurring, so inputs are not used for SPs. Forward Predict: SPs are simulated just like APs on the client, with the server sharing their inputs. But often we’re extrapolating what another client’s inputs will be, since we’re predicting a time ahead of the server. With Forward Predict, you’re likely to get a lot of corrections for a twitchy unpredictable character.
  • Turning simulation tick down: you’ll have increased perceived latency, and merging input action events over many game frames down into a single low-frequency movement input will be more important. I’m not sure of ramifications beyond that.

Got it. I was assuming that since both Mover and GAS were using NPP that if either of them said “rollback to point X” they would BOTH rollback. This implies that’s not the case, and is good to know going forward.

If I’m understanding correctly, then, the “forward predict” section is to allow “last input continuation” or some other forward prediction algorithm. I won’t get the entire input stream, just the state of the inputs on the server when the server executes its simulation tick.

So, here’s an example of what we’re looking at. We’d like the clients running at frame rate (say 60Hz to make the example easy) and the server running at 10Hz.

Client A will generate (I think) six updates as Mover runs on every frame (we want to capture the movement on every frame to render that frame’s movement as accurately as possible anyway to make the client feel snappy.) So we’ll generate six updates and send them all to the server.

The server will… queue them? Merge them? Let’s hope queue them because we need to do some kind validation to make sure the client isn’t just making things up.

So the server finally ticks, and gets some number of updates (probably close to 6, but jitter/etc who knows) and processes them. That means simulating them.

Eventually the server finishes its tick and replicates to client B.

So one question is, what does client B receive?

  1. In interpolated mode, I assume it just gets the sync state.
  2. In forward predict mode, I assume it gets the sync state and the input state from the server (see above - probably merged?)
  3. What happens to the actually generated moves? Are they ever replicated, or just built by the movement modes on the autonomous client and the server?

In either case, client B only gets one update instead of all six unless the actually generated moves are replicated too. Are they?

To clear something up, GAS is not using NPP. It has its own replication methods with no regard to what NPP or Mover is doing. GAS has a very limited concept of “rollback” where a client may, for example, predict the activation of an ability. If the server doesn’t agree that the ability was activated, the client’s ability is interrupted and canceled. Many side effects of the ability, such as applied gameplay effects, may automatically be canceled along with the ability. But if the ability has custom gameplay behavior in its Event Graph, it’s up to the ability author to handle cleaning it up upon cancelation.

Regarding client & server frame rate: there’s a distinction between the overall GAME frame rate (coinciding with rendering rate) and Network Prediction’s simulation ticking rate.

You could have a game/rendering frame rate of 60 or 120+ or have it varying in between, while still having a fixed simulation tick rate of, say, 30 fps.

If using a fixed simulation tick rate, both client and server are accumulating time and then spending it in discrete amounts (~33ms for a 30fps simulation). Client and server are all using the same simulation rate, regardless of what their game/rendering rate is. If the game/rendering rate is slow, like during a hitch or a slowdown due to intense graphics, we may get a big game frame time that results in multiple fixed-size simulation ticks during a single game frame.

So in your example, the answer depends on whether you’ve got Network Prediction using “Fixed Tick” or “Independent” ticking mode. This is unrelated to the game engine frame rate settings.

For Fixed Ticking, the clients and server are at parity. If client simulates moves for 6 frames in a row, the server will queue the inputs (along with the sim times they’re paired with) and then simulate the 6 inputs later at the appropriate simulation time. If the client’s input for a frame don’t arrive at the server in time, the server will proceed anyway using prior inputs.

For Independent ticking, the client is driving the simulation rate so the server’s low update rate is irrelevant. If the server receives 6 move inputs, it will queue them and then simulate 6 moves in a row during the single server game frame. No merging of inputs is necessary.

Client B will receive from the server:

  • in Interpolated mode: just the sync state
  • in Forward Predict mode, both sync state and input

Generated moves are just artifacts that exist in the middle of Mover’s simulation, constructed by the active movement mode & layered moves. They are discarded as soon as they’re used. Only inputs and sync state are communicated between clients and the server. Client B using ForwardPrediction will receive the latest state and input, and can forward predict from there.

Hope this helps!

Justin

This helps a lot! Thank you for taking the time, Justin.