Chaining motion warped montages

Hi,

I’m in the process of putting together a gameplay ability that allows you to chain combo moves. Each move will calculate a melee target before calling PlayMontageAndWait, similar to task to WaitTargetData. I have noticed that I often get net corrections on move 2 and move 3, but barely ever get anything on the first move.

In an attempt to understand where the point of failure is, I have stripped the ability to its bare minimum where I have 3 test points in the world that I feed to each combo section. The server and client both know about these points so there is nothing to wait for other than the input signals from the player to move on to the next combo section. This still gives me net corrections! and I’m not sure why so would appreciate some advice here.

The only way in which I have been able to make this work reliably has been to build 3 different abilities that receive a payload with the target.

I’m expecting to have combos set as different montages so I actually need to run PlayMontageAndWait. I also prefer that strategy to play next section so that I can blend out whenever needed.

How would you recommend implementing such an ability? is the only safe way via multiple abilities? if it can be done with one ability, where am I going wrong?

Diving through the code, I noticed that try activate ability is flushing server moves (I presume) to ensure that the server simulates the clients move before the montage RPC arrives. I assume this is to prevent the server from accidentally applying root motion due to older server moves that arrive after the montage RPC. I have tried flushing moves before playing subsequent sections but I still have the same problem.

Again, this is happening on a simplified task where the server does not need to wait to receive the actual target, both server and client have the same targets from the get go, but chaining montages on the same ability with warping is causing the net correction. I’m attaching a screenshot of my simplified test to give you an idea.

Steps to Reproduce
Call PlayMontageAndWait with different motion warp targets in succession.

Hey

This is generally a tough problem.. Assuming you’re using the Character Movement Component, the main issue that you’ll run into is that the RPCs for the CMC are unreliable, whereas the abilities themselves will use reliable ones. So, regardless of whether you are using a single ability or chaining them, you might be out of sync movement-wise.

I’m syncing with a dev team about your case tomorrow, but to maybe help kickstart the conversation, there are a couple of things you could try/think about.

1: Because the CMC and the abilities might be out of sync, extracting the root motion at the right time could come from client information; each client movement RPC comes with a “client time” of the movement data. We use that to determine a bunch of things in the character movement component, but for your case you could use that to wait and kick off each part of the combo. In general this could reduce the delta in the motion warp between moves making sure that your server (which is most likely ahead in playing the subsequent montages) are generally aligned time wise. This approach would require modifying the character movement component and also providing your ability with that information, which would be a heavy lift.

2: You do have the option to have client authoritative movement during the time of you ability, using the final moments of the ability to switch back to server authoritative movement. With this approach you can do everything in blueprint, but the downside is that the movement correction on the server and client might be much larger at the final sync point.

Both techniques aren’t really about when to kick off certain abilities but more about how to make sure your movement components and animation start sync points are the same.

Hi Dustin,

To add some context (and please correct me if I’m wrong here), I expect the following to happen when activating a predicted ability that plays a montage:

- Client activates ability locally

- Client flushes CMC server moves (this sends unreliable RPC to server with pending moves to simulate).

- Client sends activate ability RPC to server.

- Client runs ability activation BP which eventually creates “PlayMontageAndWait” which internally sends reliable montage RPC to server

I expect the above flow to happen within the same frame.

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)?

I have also made sure that it is a prerequisite for the movement component to run before the ability system component. I’m not sure if that is critical but it seemed like a good idea for flushing moves.

Looking more specifically into how the client packages moves and sends them to the server, I noticed that the server will use the delta time from the client to simulate the moves (which should avoid integration drift etc). I also noticed that the same delta is used to tick the pose, which should extract the root motion from any montages that are currently playing.

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?

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?

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?

Now, in regards to the solutions proposed:

  1. I’m not fully sure I’m understanding the approach here. Maybe my assumptions above are wrong, but I had the impression that the server and the client would advance through the montage with the same deltas since the server is using the deltas in the movement RPCs to tick the pose. If you could elaborate a little more here, it would be much appreciated.
  2. 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. Client authoritative and no corrections give the best results but when switching back to server authoritative you can end up in situations where the player is penetrating some collider on the server and collision resolution leads to some massive forces that sends things flying.

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:

  1. 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.
  2. 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.