No issue here. MovementSpeeds are stored in a data table on my end. If I have different characters or abilities, or combos of both I just create multiple data tables.
For example if I have a config var set on the character class I can use that to differentiate between the characters. I’d probably use a multiplier table to handle ability adjustments.
Get character table → get base speed for action → * multiplier → set speed.
This is a standard client-side prediction approach. The character movement component on both first and third player templates uses it. Works very similar. Look it up.
Apply changes locally, RPC server to make “authoritative” changes. Server will correct naturally if its changes differ.
Also, I’m using a Rep_Notify for the LocomotionMode. When the server sets the var it’s replicated over the network. No need for multicast.
The OnRep LocomotionMode function auto executes when the rep_notify var is changed. It’ll process the speed changes auto-magically.
Here’s a rough out of a working setup.
In this process I’m setting the repnotify locally which triggers the onrep function locally. This gets the speed change applied instantly for responsiveness.
Movement and speed changes are buttery smooth across all testing thresholds. 500ms pings, 10% loss etc.
The server will not make a correction until it receives data from the owning client. It doesn’t know anything changed.
The client, nor server sends an individual packet per rpc, input. Very common misconception across all game dev communities. Here, Unity, GoDot, Cry Engine etc.
Inputs, RPC’s, RepNotifies etc are buffered and bundled in a single packet for their update duration. Clients and the server send at defined frequencies.
e.g. Say the client → server update frequency is 60Hz. This means every 16.667ms all clients will send an update (packet).
Same applies to the server. 30Hz server tick means a NetFlush is executed every 33.333ms.
This reduces network saturation.