Hi, I wanted to make a simple module that makes the celestials move while I can modify how much time to spend at day time and how much time to spend at night time. I wanted to sync the time with server for timed spawnables that spawns based on day time. So, for that, functions include workspace:GetServerTimeNow().
Currently module includes:
- A function to get day time
- A function to calculate how much time is left to Daytime from current time, including next day, while keeping in mind the durations of noon-night.
-Current time can also be given as an argument so you can calculate time left to daytime from your given current time
Module
local clientFunctions = {}
--[[
* a function that calculate how much time is left to reach the daytime
* @param daytime: daytime in seconds
* @param currentDaytime: a param to overwrite current daytime
* @returns how much time is left until daytime (Including Different Noon - Night Lengths)
]]
clientFunctions.getTimeLeftUntilDayTimeInSeconds = function(daytime: number, currentDaytime: number?): number
assert(daytime <= 86400, "Day Time cannot exceed 86400 seconds.")
assert(daytime > 0, "Day Time must be bigger than 0 seconds.")
assert(daytime == math.round(daytime), "Day Time should be an integer.")
if currentDaytime then
assert(currentDaytime <= 86400, "Day Time cannot exceed 86400 seconds.")
assert(currentDaytime > 0, "Day Time must be bigger than 0 seconds.")
end
local noonLengthInSeconds = workspace:GetAttribute("NoonLengthInSeconds")
local nightLengthInSeconds = workspace:GetAttribute("NightLengthInSeconds")
local defaultNightLengthInSeconds = 43200 --(between 18 - 6)
local defaultNoonLengthInSeconds = 43200 --(between 6 - 18)
local currentDayTimeInSeconds = currentDaytime or clientFunctions.getDayTime() * 60
local timeLeft = 0
if currentDayTimeInSeconds > daytime then --daytime is in the next day
timeLeft +=
if daytime > 64800 then --next day goes beyond noon times
(nightLengthInSeconds / 2) -- night time after midnight
+ noonLengthInSeconds -- noon time
+ ((daytime - 64800) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2) -- night time after noon, to daytime
elseif daytime >= 21600 then --next day goes to noon times
(nightLengthInSeconds / 2) -- night time after midnight
+ ((daytime - 21600) / defaultNoonLengthInSeconds) * noonLengthInSeconds -- noon time, to daytime
else (daytime / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2) -- night time after midnight, to daytime
--now calculate today
timeLeft +=
if currentDayTimeInSeconds > 64800 then --currently at night time after noon
(((defaultNightLengthInSeconds / 2) - (currentDayTimeInSeconds - 64800)) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2) -- current time to midnight
elseif currentDayTimeInSeconds >= 21600 then --next day goes to noon times
((defaultNoonLengthInSeconds - (currentDayTimeInSeconds - 21600)) / defaultNoonLengthInSeconds) * noonLengthInSeconds -- noon time, to daytime
+ (nightLengthInSeconds / 2) -- night time after noon
else --currently at night time after midnight
(((defaultNightLengthInSeconds / 2) - currentDayTimeInSeconds) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2) -- current time to noon
+ noonLengthInSeconds -- noon time
+ (nightLengthInSeconds / 2) -- night time after noon
else --daytime is in current day
local timeLeftFromCurrentTimeToMidnight =
if currentDayTimeInSeconds > 64800 then
(((defaultNightLengthInSeconds / 2) - (currentDayTimeInSeconds - 64800)) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2)
elseif currentDayTimeInSeconds >= 21600 then
((defaultNoonLengthInSeconds - (currentDayTimeInSeconds - 21600)) / defaultNoonLengthInSeconds) * noonLengthInSeconds
+ (nightLengthInSeconds / 2)
else
(((defaultNightLengthInSeconds / 2) - currentDayTimeInSeconds) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2)
+ noonLengthInSeconds
+ (nightLengthInSeconds / 2)
local timeLeftFromDayTimeToMidnight =
if daytime > 64800 then
(((defaultNightLengthInSeconds / 2) - (daytime - 64800)) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2)
elseif daytime >= 21600 then
((defaultNoonLengthInSeconds - (daytime - 21600)) / defaultNoonLengthInSeconds) * noonLengthInSeconds
+ (nightLengthInSeconds / 2)
else
(((defaultNightLengthInSeconds / 2) - daytime) / (defaultNightLengthInSeconds / 2)) * (nightLengthInSeconds / 2)
+ noonLengthInSeconds
+ (nightLengthInSeconds / 2)
timeLeft += timeLeftFromCurrentTimeToMidnight - timeLeftFromDayTimeToMidnight
end
return timeLeft
end
--returns current day time in MINUTES
clientFunctions.getDayTime = function()
local noonLengthInSeconds = workspace:GetAttribute("NoonLengthInSeconds")
local nightLengthInSeconds = workspace:GetAttribute("NightLengthInSeconds")
local totalLengthInSeconds = noonLengthInSeconds + nightLengthInSeconds
local defaultLengthInSeconds = 86400
local noonNightLengthDifference = noonLengthInSeconds / nightLengthInSeconds
local differenceBetweenTotalLengthAndDefaultLength = totalLengthInSeconds / defaultLengthInSeconds
local nightStartTimeInHours = 24 - ((24 / (1 + noonNightLengthDifference)) / 2)
local nightEndTimeInHours = 24 - nightStartTimeInHours --also refers to night Length / 2
local nightLengthInHours = nightEndTimeInHours * 2
local currentTimeInSecondsWithoutWeight = workspace:GetServerTimeNow() % totalLengthInSeconds
local alpha
if currentTimeInSecondsWithoutWeight > nightStartTimeInHours * 3600 * differenceBetweenTotalLengthAndDefaultLength then --night time between 18-24
local timePassedSinceNightStart = currentTimeInSecondsWithoutWeight - nightStartTimeInHours * 3600 * differenceBetweenTotalLengthAndDefaultLength
local nightLengthInSecondsRelativeToGameTime = ((nightLengthInHours) * 3600 * differenceBetweenTotalLengthAndDefaultLength)
alpha = timePassedSinceNightStart / nightLengthInSecondsRelativeToGameTime * 2
return (18 + (alpha * 6)) * 60
elseif currentTimeInSecondsWithoutWeight < nightEndTimeInHours * 3600 * differenceBetweenTotalLengthAndDefaultLength then --night time between 0-6
--you can change it if you want, currently time passed is negative because we are in next day. So I add stuff to alpha to fix it but you can modify timePassedSinceNightStart if this looks weird/complicated
local timePassedSinceNightStart = currentTimeInSecondsWithoutWeight - nightStartTimeInHours * 3600 * differenceBetweenTotalLengthAndDefaultLength
local nightLengthInSecondsRelativeToGameTime = ((nightLengthInHours) * 3600 * differenceBetweenTotalLengthAndDefaultLength)
alpha = 1 + ((timePassedSinceNightStart / nightLengthInSecondsRelativeToGameTime) + noonNightLengthDifference) * 2
return (alpha * 6) * 60
else --day time
alpha = 1 - ((nightStartTimeInHours * 3600 * differenceBetweenTotalLengthAndDefaultLength - currentTimeInSecondsWithoutWeight) / ((24 - nightLengthInHours) * 3600 * differenceBetweenTotalLengthAndDefaultLength))
return (6 + alpha * 12) * 60
end
end
return clientFunctions
For usage you should set some attributes to workspace like this:
After that, this is how I use it client-sided:
local Lighting = game:GetService("Lighting")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
--name it whatever you want
local clientFunctions = require(ReplicatedStorage.Modules.ClientFunctions) --path to the module
local dayNightCycle = function()
Lighting:SetMinutesAfterMidnight(clientFunctions.getDayTime())
end
RunService:BindToRenderStep("Day-Night Cycle", 1000, dayNightCycle)
--clientFunctions.isDayNightCycleActive = true
--i recommend saving it to a module that you store informations at
--(both the function and boolean)
--so it is usable by stuff like ZonePlus, day night tweening for effects etc. which most likely at another script.
--That will allow you to unbind from render and bind it again when necessary
And on server-side, if you need, you can use this system to sync some spawnables / map design changes etc with daytimes like me.
This is my first open-sourced module, thanks for reading. Lemme know if there is any mistakes. Feel free to modify / fix (if any) / use it.
Just wanted to share if you want to do something similar or just check it out.