Synchronizing client effects

Hi, I’m creating a replication system where the server tells clients to play effects like particles, sounds, and tweens.

It works fine for players already in the game, since I use RemoteEvent:FireAllClients(), but the problem is players who join after an effect has started don’t see the effect or see it in the wrong state.

For example, if a tween played before they joined, the object appears in the original position for them.

What’s the best way to handle this so new players see the correct current state? Should I track effect states on the server and send them when a player joins, or is there a better approach?

Thanks in advance.

Server is the one who defines and replicates states to all clients, so practically yes, your server must also track the state of tweens and effects. Of course I understand you don’t want to define the tweens on server since Roblox’s replication system synchronizes part transforms to all clients and it naturally looks laggy. So you can keep your tweens client-side.

You can save an estimated value of tween’s playback position (currentTimestamp - startTimestamp) / duration which is value in percentage (0.0 ~ 1.0), but the hard part is tweens cannot be controlled like animation (seeking position, restarting, etc…), so with the positional value you have, the only thing you can do is sending event to new players with new modified tween where changes are applied from the time they happened before the player joined…
So if your player has joined in the middle of existing tween where part is moved from position A to position B, you have to send new tween info with the half of the duration and with part’s starting position in the middle of its trajectory.
The more complex tween, the more complex replication its gonna have.

This is a good idea. I’ll definitely implement this but I also have another question. For the latency with FireAllClients and receiving the event on the client, would it be worth trying to calculate the time difference and then subtracting the duration of the tween by that amount?

yes you may use workspace:GetServerTimeNow() when firing the event
then in client use it again to compare the time

GetServerTimeNow() returns the client’s best approximation of the current time on the server.

Alright, for everyone who comes across this post I fixed the issue by basically using what @Cloudy71 said.

So when replicating an effect, the server sends the start time: workspace:GetServerTimeNow(), and on the client, I calculate how much of the tween has already elapsed. Before starting the tween, I manually interpolate the object to the correct state using easing and lerping, so players who join late or experience delay see the tween halfway through instead of snapping or restarting.

1 Like