Movement RPCs are unreliable which could cause them to be lost and arrive out of order, however flushing the server moves should ensure the client moves are simulated on the server before the montage RPC arrives if no packet loss is encountered right (or latency spike)?
That is generally a good understanding.
So from my understanding (and again, please correct me if I’m wrong here), the montage RPC will set the active montage on the server, but root accumulation should match the client because the server will advance the montage with the same deltas as the client, since this all happens where the server simulates the client moves received from the RPCs right?
Yes but there is a caveat there that while the montage on the client and server is guaranteed to play, they may not be in sync. There could still be latency delta of the starting point. A reliable RPC to start the montage (through the Play Montage and Wait) is still subject to latency, potentially further latency because while it is guaranteed to arrive, it basically will continue to send packets until the server/client has reported it has received them all.
According to that logic, I imagine the worst case scenario happens when a movement RPC from the client is lost or delayed and the server ends up simulating it after receiving the montage RPC. That would technically mean that the server simulates client moves accumulating root motion when in reality it shouldn’t have done that, is that correct?
Yes that is possible. If the server is behind by a lot (in your case) you could have a positional correction.
In this scenario, it appears to me like with the standard setup it is impossible to guarantee no mispredicitons when triggering an animation with root motion from an ability (with or without motion warp), is that correct?
Yeah, it can’t be guaranteed without additional work. Previously, I mentioned using the ClientTime that comes from client movement RPC to use as a validation of when to trigger the montage. There is also a variable in the PlayerState->Ping, so with those you could calculate the offset from server time to “sync” up the start of your montage events as close as possible between the server and activating client. This should also answer your first question as well, but it is not safe to assume that even though you’ve triggered the server and client to play montage, that they are 100% in sync with a default setup. They will proceed with the same deltas, but the ending time might be different potentially causing a correction, and in your case, multiple as you progress further through your combo system.
We have tried not correcting the client until the move is done but unfortunately that can generate really big corrections if you collide against things that are out of sync.
Understood, this approach would require work to hook up the end sync point and handle those cases.
I took a deeper look at your graph as well, and I did notice some further problems:
- Your wait on input press is a latent action, and is also subject to latency. So when you get the input action from WaitInputPress to play the next montage you could create more out of sync montage triggering by latency.
- On top of this, because you don’t stop the previous PlayMontageAndWait async task, you could have a stack of montage tasks playing. In general, it is not a good idea to chain latent actions.
This could potentially be the bulk of your issues. I did a little bit of research to one of your first questions, and on Fortnite each combo move is a separate ability, but that is because we have further systems to manage input timing windows.
Lastly, you may also want to look into turning off MoveCombining during these actions. The character movement component will evaluate for similar movement corrections and then wait to actually do a move correction once the delta is high enough, this is tunable as well through some CVars, but I think for your case you might want to turn that off and see how that affects your capsule’s response during normal networked play.