Works in Unreal Engine 5.0 to 5.8. Updated November 2026.
Quick answer: replicate when the clock started, not the clock. Every machine works out Hours = StartHour + (ServerTime − StartTime) × 24 / (DayLengthMinutes × 60) with Get Server World Time Seconds. Replicate weather changes as a struct with RepNotify.
Why replicating the time directly goes wrong
Replicating a float that changes every frame wastes bandwidth, and clients still see it step. A Multicast event like “start rain” is worse: it fires once, so a player who joins a minute later never hears about it and sees clear skies.
The fix is to replicate a description that rarely changes and compute the rest locally.
Step 1: Store the clock on a replicated actor
Use your Game State, or an actor with Replicates and Always Relevant ticked. Add these variables, all set to Replicated:
| Variable | Type | Meaning |
|---|---|---|
| ClockStartTime | Float | Server time when the clock was last set |
| StartHour | Float | The in-game hour at that moment |
| DayLengthMinutes | Float | Real minutes per in-game day |
On Event BeginPlay, use Switch Has Authority. On Authority, set ClockStartTime = Get Game State > Get Server World Time Seconds, and set StartHour to your opening hour.
Step 2: Work out the hour everywhere
Make a pure function GetHours that every machine calls:
Elapsed = GetServerWorldTimeSeconds - ClockStartTime
Hours = Fmod(StartHour + Elapsed * 24 / (DayLengthMinutes * 60), 24)
Drive your sun from GetHours on Tick, as in How to Make a Day and Night Cycle. Server and clients read the same server clock, so they agree without sending anything per frame.
Step 3: Change the time without a jump
To skip to night or change the day length, rebase first. On the server:
- StartHour = GetHours (the hour right now).
- ClockStartTime = Get Server World Time Seconds.
- Now change one thing: set StartHour to 20 to jump, or change DayLengthMinutes to speed up.
If you change DayLengthMinutes without rebasing, the formula re-reads all elapsed time at the new speed and the sun leaps.
Step 4: Replicate the weather as a transition
Make a struct WeatherChange with FromWeather, ToWeather, StartTime and Duration. Add a variable of that type with Replication: RepNotify.
- The server fills it when the weather changes, with StartTime = server time now.
- Every machine works out the blend on Tick: Alpha = Clamp((ServerTime − StartTime) / Duration, 0, 1).
- In the OnRep function, update anything that only changes once, such as which rain sound to load.
A late joiner receives the struct and computes, say, Alpha 0.6, so they arrive part-way into the storm like everyone else.
Step 5: Let clients ask for a change
Clients can’t call server events on the Game State, because they don’t own it. Add a Run on Server event to the Player Controller, for example ServerRequestWeather. That event changes the struct on the server.
Effects don’t need replicating. Rain particles, puddles and wet materials can be worked out on each machine from the weather state. For lightning, seed a Random Stream from the weather seed plus the current half-second, and every player sees the same flash at the same moment.
Common problems
| Problem | Fix |
|---|---|
| Late joiners see the wrong weather | You used a Multicast. Use a RepNotify variable |
| Clients’ sun is a few minutes off | They’re using Get Game Time in Seconds. Use Get Server World Time Seconds |
| Far-away players stop updating | The actor isn’t relevant to them. Tick Always Relevant or use the Game State |
| Time changes on a client do nothing | Only the server may change it. Route the request through a Server event |
We use the same method in our Any Weather plugin.
FAQ
Does Get Server World Time Seconds ever jump?
It’s re-synced now and then and can step by a few milliseconds. That’s invisible for a sky, but don’t rely on it for frame-exact events.
Should the server tick the weather at all?
A dedicated server only needs the state for gameplay rules, such as “is it raining?”. Skip particles, sounds and materials there.