Now yes this is really cool but it was a ton of work, with a lot more to do! Currently I've ironed most of the desync caused by Action Script. Some Flutters pop up here and there that I have to track down. In this video the clients are running with 60 - 90 ping with 2% packet loss to simulate situations I've seen in games I play. I've tested at 200 ping with 5% packet loss and while things do degrade it's still a pretty solid experience.
** Motion Matching **
Getting MM setup was not too crazy. Epic has work to do on their end to make things more accurate for multiplayer but for me, it's fine. What I did was use the UMoverTrajectoryPredictor for the local client. For the simulated proxy I had to make copies of the functions in the pose search library. Both use the same values except the simulated proxy does not create a correct trajectory when using the predictor class. I'm hoping that will get fixed. The main issue is that Epic is using the FMoverInputCmdContext which is not serialized to simulated proxies so they have no way of using it to make movement calculations.
** Root Motion Montages **
This is built into Mover using FLayeredMove_AnimRootMotion by default it does not support stopping after it has already started which was a big pain point for me. There is no mutable access to the layered moves once they start so I had to create a child of this struct and override GenerateMove() to check for some custom flags I put in the sync state. It's working but it's not perfect. At higher pings Mover seems to always correct the location of the player towards the end of this layered move, even if you let it complete all the way through. I'm still investigating why this happens but for now I'm happy where it is.
** Custom Ability System**
For the past year I've been iterating on a GAS like way of writing abilities using Mover for the movement and all of the other sexy things NPP has to offer. Since GAS doesn't work out of the box you essentially need a custom object that
- Ticks with the simulation
- Keeps track of it's state and any child object states
- Can rewind to a previous frame and simulate to a current frame staying in sync with the server's authoritative state.
Honestly this has been the most difficult part and it's **SUPER **experimental. I can't wait for Kai to finish his GAS integration that will come with some higher end and much needed features like Delta Serialization. NPP's biggest issue (next to no one documenting their usage 👀 ) is how bandwidth hungry it is. I'm using a custom version of the plugin modified by Kai that takes a bite out of that chunk but it's no where near what GAS can do network performance wise.
Action Script is a heavily modified version of Flow Graph. It's super clunky compared to a normal blueprint but it creates the exact restrictions that are need for things to stay in sync. Things like delegates, latent functions or anything that is based on the default unreal clock can throw the entire simulation out of whack due to the fact they work on different clocks. The original comes with some built in nodes that you can use as an example to get started but I pretty much gutted most of them. With the help of another user I was able to integrate FInstancedPropertyBag allowing the graph to feel more like a blueprint. I've also added support for custom events and graph parameters. You can see in the screenshots that I have a ton of GAS muscle memory. As it stands now all nodes must be created from scratch, but I'm looking into allowing internal functions as well as supporting calling external functions. Like I stated in the beginning there's still a ton of work left. I'm over a year in and I'm just now able to start making stuff with it. Lol
While I am boasting about my own achievements, I'm hoping this will inspire more people to start using Mover & NPP.
While you're here subscribe - https://www.youtube.com/@AntiHeroGameStudio
✌🏿 🍻