Mover: Best Practice for Root-Motion Traversal, Server Animation, and Client Prediction?

Hi!

I’m doing some pre-production research for a multiplayer game using Mover and Motion Matching for locomotion. Most of my previous experience has been in single-player gameplay/animation systems, and this is also my first project using Mover, so I’m trying to make sure we choose the right architecture early.

The game is relatively small in terms of character count: around 6–7 players + 1–2 AI NPCs in a dedicated server session.

I’m trying to understand the recommended approach for high-accuracy animation-driven movement, such as:

  • traversal / mantles / vaults
  • vent interactions / smart navlink-style transitions
  • synced or semi-synced interactions
  • other committed movement actions that would traditionally use root motion montages + Motion Warping

My initial idea was:

  • clients run the full Motion Matching / procedural adjustments / layering, etc… ABP
  • the server uses a much simpler animation setup: ABP would only keep the montage slots needed for animation-driven moves
  • committed moves would use Mover root-motion layered moves / montage-based movement on the server.

However, I’m unsure whether, for performance reasons, we should try to completely skip animation evaluation on the dedicated server. Right now, some gameplay flow inside Gameplay Abilities relies on montage events such as Montage End, Blend Out, Interrupted… If we completely skip server animation, I assume we would need to refactor that gameplay flow so it is driven by gameplay state/timing data instead of montage events.

So my main question is:

For a game with a relatively low character count, is it reasonable to keep a minimal server animation setup with montage slots so montage/root-motion-driven gameplay flow can still work, or is the intended/robust approach to avoid server animation dependency entirely? I may be overthinking this given the small number of characters, but I would like to understand what Epic or other teams using Mover would recommend.

I’m also trying to understand the expected synchronization model for local prediction.

For example, suppose the local client presses Interact:

  1. the client wants to play the montage immediately for responsiveness;
  2. the client asks the server to validate/start the interaction;
  3. the server starts the authoritative Mover root-motion layered move;
  4. the server replicates the interaction state back to the owning client and simulated proxies.

If the owning client only plays the montage locally without movement, the visual animation and the authoritative root-motion movement can be desynced for a few frames. With higher latency this may become visible. What is the usual way to handle this with Mover?

  • Should the owning client also start a predicted Mover root-motion layered move locally, then reconcile when the server confirms?
  • Should the owning client only play an anticipation section locally and wait for the server before applying movement?
  • Should clients set or smooth the montage position based on the server start time of the layered move?
  • For simulated proxies, is the expected approach to start the montage at the replicated server phase rather than from the beginning?

I would appreciate any guidance on the intended pattern for these cases

Thanks!

[Attachment Removed]

Steps to Reproduce
none

[Attachment Removed]

Hey there,

Apologies for the delay. Epic has been on break, and we’re just catching up. Generally speaking Mover should be able to support your needs pretty well. Alongside some answers to your direct questions I have some suggestions for you to look into for your game based on how you’ve described.

However, I’m unsure whether, for performance reasons, we should try to completely skip animation evaluation on the dedicated server. Right now, some gameplay flow inside Gameplay Abilities relies on montage events such as Montage End, Blend Out, Interrupted… If we completely skip server animation, I assume we would need to refactor that gameplay flow so it is driven by gameplay state/timing data instead of montage events.

Being capsule-driven with animation following will generally serve you best. And you can turn off most animation on the server. The only ones you probably won’t be able to use are your abilities that use montages; those should still play on the server for any warping or root motion-driven abilities. Generally, just saying that your assumptions are correct there.

If the owning client only plays the montage locally without movement, the visual animation and the authoritative root-motion movement can be desynced for a few frames. With higher latency this may become visible. What is the usual way to handle this with Mover?

We don’t typically recommend having the montages play differently in terms of root motion, so I wouldn’t recommend playing the montage without movement. Ultimately, the goal is to get the Layered Moves from Play Montage (Mover) to be predicted as much as possible. We have two examples, but I would recommend looking at how we handle vaults inside of the MoverExamples plugin. This shows how we use inputs passed through Mover to then call the vault, leading to that being a better predicted move. The Game Animation Sample does it another way, where it’s a bit more client-initiated than reliably replicated via RPC. The issue though is that this could lead to a stronger correction if there is a disagreement of state.

Should the owning client also start a predicted Mover root-motion layered move locally, then reconcile when the server confirms?

This is what the Mover example does, but there is no reconcilation, it will just allow or disallow it. If the server disallows it, the layered move will just be cancelled as soon as there is a disagreement.

Should the owning client only play an anticipation section locally and wait for the server before applying movement?

This is up to you and your design. I have done a similar approach to this in the past to hide latency in the anticipation of a move to allow time for the server to receive the action. This was done with CMC though, and shouldn’t be as necessary with mover and NPPM.

Should clients set or smooth the montage position based on the server start time of the layered move?

We don’t recommend this to start, like mentioned above you shouldn’t need it.

For simulated proxies, is the expected approach to start the montage at the replicated server phase rather than from the beginning?

Because of the recommended infrastructure, when Mover replicates that’s when the simulated proxies should replicate their layered move.

For the Game Animation Sample, we tuned a few networking properties that you might want to look at as well.

It’s probably a good idea to boost your network cap rate a bit.

  • This is NetDriver settings like MaxClientRate, MaxInternetClientRate, and Player settings like ConfiguredLanSpeed/ConfiguredInternetSpeed

We have some help is coming in the form of delta compression, so the server -> sim proxy movement traffic will shrink a lot and you can reduce it without a bunch of quality loss.

Boosting the internal buffering of NPP can help reduce errors in NPP and rubberbanding in high latency or scenarios with a lot of characters (think high 20’s and 30s). Which one you tune will be based on which model you’re using.

  • Fixed Interpolation Buffered MS
  • Independent Tick Interpolation Buffered MS
  • Independent Tick Interpolation Max Buffered MS

Hope this helps you out.

Dustin

[Attachment Removed]

Thank you Dustin, this is really helpful.

I actually reached a similar conclusion on my side before seeing your reply: that the root motion should be treated as a Mover input and predicted through the simulation, instead of being started by an RPC. It is good to have that confirmed.

I didn’t know about the vaulting example though, so thank you for pointing me to it. I went to check it, and what I found was at the physics-simulated character level, where the pawn is using the ChaosMoverComponent. Before I go deeper, I want to make sure that is the example you meant, because it changes one important thing for me: whether the recommended approach is tied to the Chaos backend or not.

So my question is: does the input-route predicted montage (Produce Input > OnPreSimulationTick > Play Montage) work on CharacterMoverComponent as well, or is ChaosMoverComponent required for it to predict and resimulate correctly? Is the committed-move pattern you are recommending tied to the Chaos / NPP backend?

One more note: at least in 5.7, I could not get the vaulting to fully work on my side. The montage animation plays, but it plays in place. Not sure if this is a known issue in 5.7 or a problem on my end. I’d expect us to move to 5.8 in the short term but probably we will start in 5.7 and it would be good to know possible issues.

Thanks again for the help.

[Attachment Removed]

So my question is: does the input-route predicted montage (Produce Input > OnPreSimulationTick > Play Montage) work on CharacterMoverComponent as well, or is ChaosMoverComponent required for it to predict and resimulate correctly? Is the committed-move pattern you are recommending tied to the Chaos / NPP backend?

CMC doesn’t really follow that pattern in terms of networking, you would need to modify CMC to do that. The pattern recommended is for Mover and NPP.

One more note: at least in 5.7, I could not get the vaulting to fully work on my side. The montage animation plays, but it plays in place. Not sure if this is a known issue in 5.7 or a problem on my end. I’d expect us to move to 5.8 in the short term but probably we will start in 5.7 and it would be good to know possible issues.

Is it set for root motion? If you were to follow GASP, that is a good template for how you would want that to work.

Dustin

[Attachment Removed]

Hey Dustin! I should have said just “Mover” instead of CharacterMOVERComponent because it can easily mistaken for CharacterMOVEMENTComponent, they are both CMC hehehe. GASP uses that component so I assumed I’d use it as well. But in the MoverExamples you mentioned the Pawn class that has the Vaulting functionality uses ChaosMoverComponent, just wanted to be sure if I’m safe using the kinematic Mover version to follow the pattern we talked about or I need to use also Chaos version of it.

Thanks

[Attachment Removed]

Ah apologies,

I would recommend using the NetworkPredictionLiason, not the Chaos version. When using the NPP version, you’ll always want to try out and see which ticking policy works best for your game and your rollback needs, whether it’s fixed or independent.

Dustin

[Attachment Removed]

Sorry for the delay Dustin and Thank you very much!!

[Attachment Removed]