TimeOfDay is an environment object that drives the level day/night cycle.
It calculates sun elevation and azimuth from a normalized time value and broadcasts updates to subscribed environment systems such as sky, sun, scatter sky, exposure, and lighting components.
TimeOfDay is commonly used with advanced lighting and a compatible sky object, such as ScatterSky.
TimeOfDay only has a visible lighting effect when other environment objects listen to it or use its sun/time data. By itself, it is a global time controller, not a sky renderer.{
"class": "TimeOfDay",
"name": "tod",
"axisTilt": 23.44,
"dayLength": 1800,
"startTime": 0.15,
"time": 0.15,
"play": false,
"azimuthOverride": 0,
"dayScale": 1,
"nightScale": 2,
"enableStartTimeFallBack": false,
"position": [0, 0, 0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [1, 1, 1]
}
| Field | Type | Description |
|---|---|---|
class |
string | Must be "TimeOfDay". |
name |
string | Scene object name, commonly "tod". |
axisTilt |
number | Sun path tilt in degrees. |
dayLength |
number | Length of a full virtual day in real-world seconds. |
startTime |
number | Time used when the level starts. |
enableStartTimeFallBack |
bool | Compatibility mode for old/non-normalized time setups. |
time |
number | Current normalized time of day. Hidden in inspectors. |
play |
bool | Whether time advances automatically. |
azimuthOverride |
number | Fixed azimuth angle. Non-zero disables normal axisTilt azimuth behavior. |
dayScale |
number | Time multiplier while the sun is up. |
nightScale |
number | Time multiplier while the sun is down. |
TimeOfDay uses normalized time:
0.0 -> start of cycle
0.25 -> quarter through cycle
0.5 -> halfway through cycle
0.75 -> three quarters through cycle
1.0 -> wraps to 0.0
When assigned through setTimeOfDay, time is wrapped into the 0..1 range:
mTimeOfDay = time - floor(time);
Examples:
| Input | Stored time |
|---|---|
0.15 |
0.15 |
1.15 |
0.15 |
-0.1 |
0.9 |
A common daylight start value is around:
"startTime": 0.15
The exact visual result depends on sky/sun setup and azimuthOverride.
"startTime": 0.15
startTime is copied into the current time when the object is added.
If compatibility fallback is disabled:
time = startTime
If enableStartTimeFallBack is enabled and azimuthOverride is non-zero, the engine applies an offset:
time = (startTime + 0.75) % 1.0
This exists for compatibility with older levels.
"time": 0.15
time is the current normalized time of day.
It is a protected field and hidden in inspectors. Setting it calls setTimeOfDay(), which wraps it and immediately updates sun position.
For level files, startTime is usually more important than time, because onAdd() resets time from startTime.
"play": true
When play is true, the time advances every simulation tick.
The update uses:
deltaTime = tickSeconds * simulationTimeScale * dayOrNightScale
time += deltaTime / dayLength
If play is false, the time remains fixed unless changed by script/editor or animation.
"dayLength": 1800
dayLength is the length of one full virtual day in real-world seconds.
Examples:
dayLength |
Meaning |
|---|---|
600 |
10-minute day |
1800 |
30-minute day |
3600 |
1-hour day |
86400 |
Real-time 24-hour day |
Use longer values for slow natural progression and shorter values for visible day/night cycles.
"dayScale": 1,
"nightScale": 2
dayScale and nightScale multiply elapsed time depending on whether the sun is considered up or down.
In code, day/night selection is based on the normalized sun elevation:
day scale is used when elevation is > 350 degrees or from 0 to < 190 degrees
night scale is used otherwise
This means a level can make nights pass faster than days:
"dayScale": 1,
"nightScale": 4
TimeOfDay calculates:
These values are broadcast through TimeOfDay::smTimeOfDayUpdateSignal.
"axisTilt": 23.44
axisTilt is the angle in degrees between the global equator and tropic.
The default Earth-like value is:
23.44
In the simplified calculation used by this implementation, axis tilt affects the sun path when azimuthOverride is not set.
"azimuthOverride": 0
When azimuthOverride is non-zero, the sun keeps a constant azimuth angle through the day.
This disables normal axisTilt-based azimuth behavior.
In this mode:
elevation = ((time + 0.25) % 1.0) * 360 degrees
azimuth = azimuthOverride
The 0.25 offset compensates for the azimuth override time shift used by older content.
Use this when you want a fixed sun compass direction while still allowing elevation to change.
TimeOfDay initializes an internal sun color curve.
The curve maps normalized elevation to colors for:
The built-in color targets range from:
0 radians -> high noon
PI radians -> midnight
The default curve gradually transitions from white daylight to warm dawn/dusk colors and darker bluish night colors.
These targets are internal in this implementation and not exposed as persistent fields in the shown code.
When a TimeOfDay object is added:
time from startTime.onAdd script callback.When removed, it is removed from the scene.
TimeOfDay supports animated transition toward a target angle.
The method:
animate(f32 time, f32 speed)
takes:
| Parameter | Meaning |
|---|---|
time |
Target time angle in degrees, clamped to 0..360. |
speed |
Animation speed in degrees per second. |
Internally, current normalized time is converted to degrees:
currentDegrees = timeOfDay * 360
If the target is behind the current time, it wraps forward by 360 degrees so animation always proceeds forward through the day.
Example concept:
current = 90 degrees
target = 45 degrees
actual target = 405 degrees
The animation stops when it reaches the target.
{
"class": "TimeOfDay",
"name": "tod",
"axisTilt": 23.44,
"dayLength": 1800,
"startTime": 0.15,
"time": 0.15,
"play": false,
"azimuthOverride": 0,
"dayScale": 1,
"nightScale": 1,
"enableStartTimeFallBack": false
}
Use this for a fixed time of day.
{
"class": "TimeOfDay",
"name": "tod",
"axisTilt": 23.44,
"dayLength": 2400,
"startTime": 0.2,
"time": 0.2,
"play": true,
"azimuthOverride": 0,
"dayScale": 1,
"nightScale": 3,
"enableStartTimeFallBack": false
}
This creates a 40-minute full cycle with nights moving 3x faster than days.
{
"class": "TimeOfDay",
"name": "tod",
"axisTilt": 23.44,
"dayLength": 1800,
"startTime": 0.12,
"time": 0.12,
"play": false,
"azimuthOverride": 135,
"dayScale": 1,
"nightScale": 1,
"enableStartTimeFallBack": false
}
Use azimuthOverride when you want the sun to rise/lower along a fixed direction for art direction.
{
"class": "TimeOfDay",
"name": "tod_preview",
"axisTilt": 23.44,
"dayLength": 120,
"startTime": 0,
"time": 0,
"play": true,
"azimuthOverride": 0,
"dayScale": 1,
"nightScale": 1,
"enableStartTimeFallBack": false
}
Useful for quickly checking lighting transitions.
TimeOfDay does not render the sky or sun by itself.
It is intended to work with environment objects that listen for time updates, such as:
ScatterSkyTimeOfDay::smTimeOfDayUpdateSignalTimeOfDay update signal.TimeOfDay object per level.startTime for the level’s initial time.time and startTime consistent in saved files for clarity.play for fixed-lighting maps.play only when the level should have a moving day/night cycle.dayLength values unless you intentionally want fast cycling.nightScale to make night shorter in gameplay.enableStartTimeFallBack disabled for new content.azimuthOverride only when you need fixed sun direction.ScatterSky.Possible causes:
ScatterSky or sun object is not connected to the TimeOfDay update signal.play is false and the time is not being changed.Check:
"startTime": 0.15
Remember that onAdd() initializes current time from startTime.
If enableStartTimeFallBack is enabled and azimuthOverride is non-zero, a compatibility offset is applied.
For new levels, use:
"enableStartTimeFallBack": false
Increase:
"dayLength": 3600
Also check:
"dayScale": 1,
"nightScale": 1
and simulation time scale.
Increase nightScale:
"nightScale": 3
This makes time pass faster while the sun is down.
Check:
"azimuthOverride": 0
If azimuthOverride is non-zero, it forces a fixed azimuth and disables the normal azimuth calculation.
Also check axisTilt.
TimeOfDay is the level day/night controller.
It stores normalized time, advances it when play is enabled, calculates sun elevation and azimuth, and broadcasts time updates to sky/lighting systems. Use it with a compatible sky object such as ScatterSky for visible day/night lighting changes.
Was this article helpful?