Tutorial: Smooth Day and Night Cycle

A presentation about solutions to creating a day and night cycle in Roblox
Like with all my tutorials, a video guide is available at https://www.youtube.com/@aargon1475

Alternative solutions, and drawbacks

I. A while loop on the server

In a script in ServerScriptStorage, put:

while true do game.Lighting.ClockTime += 0.001; wait(0.01) end

Very smooth, but the degree of control is limited. The slowest smooth rate of progression is 0.1 hours per second. Increasing the delay between increments beyond 10ms begins to stratify the skybox's movement.

Best solution

II. Server-side Tween

In a script in ServerScriptStorage, put:
local ts = game:GetService("TweenService")
--for more information, view https://create.roblox.com/docs/reference/engine/datatypes/TweenInfo
--in order, length, easing style, easing direction, repeats, reverses, delay
local night = TweenInfo.new(6 * 60, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false, 0)
local day = TweenInfo.new(15 * 60, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false, 0)

function first()
	local t = ts:Create(game.Lighting, day, {ClockTime=24})
	t.Completed:Connect(second)
	t:Play()
end

function second()
	local t = ts:Create(game.Lighting, night, {ClockTime=12})
	t.Completed:Connect(first)
	t:Play()
end

game.Lighting.ClockTime = 14

first()

Very smooth and enables a much, MUCH greater degree of control over how the day progresses.

Explanation

A tween is a construct which defines the transition from one state to another of an element. Tweens are bi-directional and always take the shortest path, meaning a tween from position A to position B will always be in a straight line. Additionally, tweens have a set amount of time to bring about the change in value. At the end of a tween, it directly sets the object's value to the end position.

Let us mention how Lighting.ClockTime works: Lighting.ClockTime represents a 24-hour clock and values above 24 are taken as modulo 24. Therefore, when Lighting.ClockTime == 24, the end of the first tween, Lighting.ClockTime actually equals 0, after being rectified by the server.

First, we call on the TweenService and assign it to variable ts. Second, we define two "TweenInfo" constructs. TweenInfo carries the information required by TweenService:Play() to perform the tween operation. Tween-infos are like tables that ocntains the properties of the tween. The value in using a tween-info is that the information is reusable. As can be evinced, the first tween-info carries the information for the tween that plays at day, and the second tween-info carries the information for the tween that plays at night. The night tween-info is shorter, because I wanted it to be. Feel free to change it as you see fit. The tween is linear, meaning it will evenly progress the ClockTime value of game.Lighting from 0 to 24 over the course of its respective duration, which is in seconds. Feel free to change every value but repeat, because repeat prevents Tween.Completed from firing.

Because we are using Event:Connect() to connect to an event, and we want to reuse the function we are connecting, we define two functions, first and second . First runs the first half-tween, second runs the next half-tween. Each function is a mirror of the other, having goals on opposite ends (12 for midday, 24 for midnight), and each connects to the other after the tween is completed through the Tween.Completed event.

Lastly, we set the game's time to be 14, which runs only once, and then we start the first() function, which will calls second() once its tween finishes, and second() will then call first() once second's tween finishes, forming a loop.

So, the first tween will play, then the tween will reach the end point, 24, at which point the first tween ends, the server rectifies 24 to 0, and the next tween plays, which brings the value 0 to the value 12. At this point, the 0 to 12 tween is completed and the first tween is replayed, looping forever and forming the day and night cycle of your game.

Addendum

There are interesting Enum.EasingStyle values for you to choose from. Cubic, Quad, Quart, Quint, Exponential, and Circular are all more extreme versions of the same exponential curve; Linear is a constant increase towards a value, like moving at a constant velocity; Sine produces a repeating and very elegant curve, which is good for smooth, looping animations; Bounce and Elastic are silly, but sometimes useful and very amusing.

You can view these curves here but be aware, all of them are for Enum.EasingDirection.In, meaning by default, the curves play backwards; so Bounce with Enum.EasingDirection.Out plays like a bouncing ball coming to rest, but with Enum.EasingDirection.In, plays like a kid jumping on a trampoline.