Yeah, it’s definitely looking like a replication issue then. I have spent a lot of time battling replication for movement controls and rotations and I hear a lot of people say do it this way or that way, but those solutions never proved fruitful for me. This is especially true on dedicated servers in conjunction with options for LAN sessions. They certainly behave differently than one another.
Rotation is in relation to pitch, finding out in a hard way, not replicated out of the box at all. It needs to be replicated on tick or timers and passed to your animation blueprint. I also found that replicating on LAN is also different than dedicated servers and movements don’t replicate like they do there. I had issues with rubber banding and solve them completely in the LAN session solution just to package a dedicated server to find the clients couldn’t move at all.
Now this is on a character and not a flying vessel, but my solution goes like such:
I feed my axis values into two separate events. One RunOnServer event and one RunsOnOwningClient event. These are not reliable for the network’s sake.
On the server event it calls an unreliable multicast event that executes the movement logic like normal and passes the axis value from the server event to the multicast to the add movement node.
On the owning client event it simply executes the logic like normal as well by passing the axis value to the add movement input node like the multicast event.
From here I am perfectly in sync on client and server no matter what. You could probably make this work with on rep functions, but it wasn’t nearly as straight forward as this approach.
Before I get any lashings from the community about clogging the network with so many server calls, I can say that this is not a cause for concern in my testing and these are unreliable and you still have network prediction for any lag that occurs. The movement inputs over the server represent a tiny execution of data. Mostly on the lower end of the scale of like no more than 3-100 BITS not bytes of data confirmed in the network profiler. So only whilst moving you are sending and receiving a negligible amount of data unreliably and even so you can tune down the update frequency on the actor to optimize further.
Now comes the part where the rotation still rubber bands or doesn’t replicate at all. For this I implemented a function I named “ControlRotation”.
It looks like this:
It was important to note that this variable needs to be replicated and marked to “SkipOwner”.
For this to update at an acceptable rate it needs to be on tick or a timer at appropriate intervals. It’s not very performance heavy despite being on tick either I can still churn out many hundreds of FPS without consideration to anything else going on in the game.
Now I have a replicated rotation variable I can use in the animation blueprint I implemented like:
Now that I have this variable in place in the anim blueprint I can set my pitch and we are moving around like butter, pitching up and down, moving left and right, frolicking around without any rubber banding at all while only sending a tiny bit of data to and from the server.
As far as updating movement speed, I addressed this by just updating the movement speeds at the tail end of my add movement with a series of branches that set the appropriate speeds depending on what is true or false because it was the only way I found to reliably update the speeds without getting out of sync with my logic. So in lieu of setting faster speeds when sprinting or running an afterburner on a button push, I set a boolean variable true or false and the branch checks after the add movement catch this and set everything appropriately and reliably because it’s happening very frequently.
Sorry this became very long. It’s a bad habit of mine. I’ve tested this across the country on remote servers and can verify excellent results. Hopefully it helps you or others. I’m open to input or criticism on the subject or any clarification on what I rambled on about lol.