I am trying to implement a stamina system for my mmo. In few words, I computed everything on the server that then notifies the client. On the client I have a stamina bar that shows the stamina amount. My problem is that the values on the server and the one on the client often go out of synch because of network delay and that causes odd behaviours on the bar.
There are things that can affect the regeneration/depletion of a stat. My architecture is server authoritative and the server is in charge of handling the flat changes and the changes in the delta amount per second, that's a constraint.
END EDIT 2.
The communication scheme is between Client (C) and server (S) is the following:
C: me want use stamina
S: ok your stamina is X descreasing at Y/s
C: set stamina to X and animate the bar accordingly to Y/s
every 1 sec after this initial handshake
S: this is your stamina X_i and it is decreasing at Y_i/s
C: use information to animate the stamina bar coherently yet in a way that resembles linearity
as soon as S knows stamina is 0
S: your stamina is 0
C: set stamina bar to 0
Due to loss of synch, the value 0 may appear when the real value is not really 0. The client holds a float amount that is decreased/increased and ceiled to int at every frame to be displayed.
Options I have already tried:
-Whenever the server updates you, force its value: causes jumpy behaviours and doesn't achieve fake linearity
-Whenever the server updates you, calculate the client regen/loss factor as (server amount + delta amount per second) - client amount. Causes the most overshots (client value going to zero when it should not be 0).
-Whenever the server updates you and you find a delta between the server value and the client value, run a coroutine that adds/subtracts over two or three frames that delta to the client value. Still too jumpy and sometimes the error is so big it makes the bar make huge leaps.
Language c#, network library photon, engine unity.
My partial solution has been:
The server sends you an update including a duration and a target value predicted for when that duration has elapsed. The client at each update starts a tweener (DOTween library) from it's current value to the target value over that duration. I had the issue that sometimes the client would display 0 when it wasn't the case on the server due to network delay that didn't stop the client in time, and if you reach 0 in my case I have to perform a cooldown wait that wasn't happening being the command to start the cooldown issued by the server. So what I've done has been to make the server accept the 0 from client when it was the case. It seems to work but on changes on the delta value per second, sometimes it might slow down or get quicker in a way that it is noticeable, sometimes.
END EDIT 1.
Additional tweak that makes it look a little better.
When the event that starts/stops consuming the stat occurs in the client, I stop the stat bar and wait for server update.
END EDIT 3.