I'll show my two different attempted solutions with the drawbacks of each:
A.
while true do local minutes_after_midnight = lighting_service:GetMinutesAfterMidnight() if minutes_after_midnight > 59 and minutes_after_midnight < 421 then wait(speed_wait_time) else wait(default_wait_time) end minutes_after_midnight = lighting_service:GetMinutesAfterMidnight() local new_minutes_after_midnight = minutes_after_midnight ~= 1439 and minutes_after_midnight + 1 or 0 lighting_service:SetMinutesAfterMidnight(new_minutes_after_midnight) if new_minutes_after_midnight == 0 then day_number = day_number < 7 and day_number + 1 or 1 current_day.Value = days[day_number] end end
This one works great. It was also the first I made. However, the sun and moon in the sky are jerky in their movement, which is what I want to fix about this bit of code.
B.
while true do local current_clock_time = lighting_service.ClockTime local new_tween_obj if current_clock_time > 0 and current_clock_time < 7 then new_tween_obj = tween_service:Create( lighting_service, speed_wait_time, {ClockTime = current_clock_time + 1} ) else new_tween_obj = tween_service:Create( lighting_service, default_wait_time, {ClockTime = current_clock_time + 1} ) end new_tween_obj:Play() new_tween_obj.Completed:Wait() new_tween_obj:Destroy() if current_clock_time + 1 == 24 then day_number = day_number < 7 and day_number + 1 or 1 current_day.Value = days[day_number] end end
This one works fairly well, but, depending on the time set for how long the tween will take, the clock on the client will display time inconsistently (i.e. skip a minute or several minutes).
I'd appreciate any fixes, alternative solutions, or advice you have to give. Thanks!
Firstly, test how much time should an entire cycle should run in real life and then you can convert that to ingame time. For example, Minecraft takes 20 minutes and Terraria 24 minutes, both of them make easy to fit in our 24h clock.
After picking a cycle, you can make a simple equation where every second you sum the "TimeInGame" with a constant. Also, when the "TimeInGame" is >= 24 you can just set the time back to 0. (If you work with minutes, 1440 minutes is the same as 24h)
Here my example I did while learning how to do the cycle with hours, this one there ins't any extra time during sunrise/moonrise or sunset
local hours = 0 --time in hours in the game local Lightning = game:GetService("Lightning") repeat hours = hours + 0.1667 -- that number is a constant you discover by doing rule of three (i.e 1 minute irl = 1 hour ingame... 1 second irl = X hours ingame) game.Lightning.ClockTime = hours --Using time ClockTime because it uses hours wait(1) if hours >= 24 then --This If makes sure my cycle will not be stuck on 24:00 forever hours = 0 end until hours == 24 --the loop won't stop until it gets exactly at 24h, which will never happen end
I hope this one gave you a simple idea of how to smooth it.
To begin with, what I see you're doing is creating a tween, playing it, and only once it has completed doing its thing, you update values such as the current minute, and day.
What we want to do instead, is update these values each frame. We can do this by utilising RunService.Heartbeat:Connect()
Now, if we want to set the actual time, we have 2 ways of doing so: Sync the current time up with the time on the server/client Create a new variable which holds the time
Using both techniques would allow for manipulating the speed that time passes through mid-way, but using the first one is overly complex and not worth it, so we're using a variable instead. In the case of the script that I'm using, Lighting.ClockTime is where we store the variable.
Now, as for changing the time, we will do so using the DeltaTime parameter passed to the function passed to Runservice.Heartbeat:Connect(). I usually tend to shorten it to dt, so I'll call it that for the rest of the explanation.
Now, if we were to simply add dt to Lightning.ClockTime, we'd already have a functional clock, at the speed of 1 hour per second. However, I believe that you want to use a different speed, and be able to change it anytime you wish to.
So, in order to accomplish that, we'll simply multiply dt with the speed we want, measured in hours per second, and we'll change the number we multiply dt with based on conditions that you can set as you wish.
Now, putting all of this together will result in the following piece of code:
game:GetService('RunService').Heartbeat:Connect(function(dt) local CurTime = game.Lighting.ClockTime IsFast = false if (CurTime > 0) and (CurTime < 7) then IsFast = true end local SpeedMul = DefaultSpeed -- I'm using this setup so you can add more cases for speeding up the time at different paces, if needed. if IsFast then SpeedMul = FastSpeed end -- This is the part that actually changes the time. game.Lighting.ClockTime = game.Lighting.ClockTime + dt * SpeedMul if CurTime + dt > 24 then -- This is fired everytime it's midnight, just as happened in your own example day_number = day_number%7 + 1 -- This is a faster way to increase a number by 1, and make sure it's in between 1 and 7 current_day.Value = Days[day_number] end -- You can use these for an accurate measurement of time local Hour = math.floor(game.Lighting.ClockTime) local Minute = math.floor((game.Lighting.ClockTime%1)*60) local Second = math.floor((game.Lighting.ClockTime%(1/60))*3600) end)