I’m working on a multiplayer row boat racing game where there are 4 players on each boat. The amount of force added to the boat is determined on input timing with a slider, and the faster the boat is going the faster the slider moves therefore making accurate inputs more difficult.
The issue I’m having is syncing the slider position between all the players on the boat. At the moment the slider position is being updated in the widget UI blueprint. This works, however the slider position isn’t synced between players because it begins its loop when the UI is created by the player controller. So depending on when the player is logged in, that’s when the loop starts which causes a desync.
I tried adding a timer in the gamemode that triggers a custom event in the UI every every 0.01 seconds to replace the event tick but it made things even worse. What’s the solution here?
Usually it is a bad idea to have a widget hold state for gameplay logic. Widgets are only client side and supposed to pull data from elsewhere, this way it can never desync and should never get outdated.
Put all state on the boat instead of the widget. One property holds the gametime which is the optimal time to row which can be visualized as a point on the slider. The Widget simply pulls that time and visualizes it as a slider. the boat must be replicated.
moved the whole timer system that sets and resets the slider into the boat pawn blueprint and just referenced the value in the widget. Its pretty much working the same way it was before and the desync is about the same.
Hard to tell what else is going on without seeing it. I would get rid of all the delays and simplify.
Boat:
Property float Speed.
Property float NextRowGameTimeSeconds.
Property int32 PlayerRowedCount.
Each rowing “cycle” requires that all players row once to complete. At the start of a cycle PlayerRowedCount is set to 0. NextRowGameTimeSeconds is calculated from the current game time (AGameState::GetServerWorldTimeSeconds) + a few seconds into the future. The added amount is less when going at high Speed. NextRowGameTimeSeconds becomes the next most optimal time for all players to row and must be replicated. This must be in sync for everyone at all times (verify that it is). This optimal time is represented as the center of your widget its slider. Anything less or more moves the slider towards the left or right into the red. The slider should read directly from NextRowGameTimeSeconds on the boat. After a player hits the row button PlayerRowedCount is increased once per player. After they all did row the cycle repeats.