In this tutorial, I’m going to show you how to make a simple clock using CFrame
. In the end, you should have something like this:
Creating the hands
Add two parts into workspace.
One hand will be the short hand and the other will be the long hand. (Feel free to rename the hands to avoid confusion).
Resize the long hand. The short hand must also be resized—to about half the long hand’s size.
Now you can duplicate each hand and do the following:
- Resize each part and position it to the end of the hand.
- Rename them both “Pivot”.
- Group each hand along with its pivot.
- Set each hand’s primary part to its pivot.
- Group both hands into one model.
- All parts have to be anchored.
GIF and video demonstrations
Now place the short hand on top of the long hand; in the screenshot below, I gave the short hand a different color to avoid confusion.
Spinning the hands
Now we want the hands to actually move. (more specifically, spin!) Time to start scripting.
We want something like this:
So add a script inside the model and here’s what you’re gonna do:
- a. Get your variables
local hands = script.Parent
local longHand = hands:WaitForChild("LongHand")
local shortHand = hands:WaitForChild("ShortHand")
local longHand_Pivot = longHand.PrimaryPart
local shortHand_Pivot = shortHand.PrimaryPart
- b. And since we’re dealing with time…
local lighting = game:GetService("Lighting")
local minutesInAnHour = 60
- c. Get the origin CFrame of each pivot since the clock in general should be stationary.
local longHandOrigin = longHand_Pivot.CFrame
local shortHandOrigin = shortHand_Pivot.CFrame
local function getTwelveHourClock()
end
This is one of our main functions we will use; I’ll talk more about this later.
- a. Create a loop
while wait() do
end
- b. Rotate the hand model (by its pivot).
longHand:PivotTo()
shortHand:PivotTo()
To rotate a model by it’s origin, we could do:
model:PivotTo(CFrame.new(model.PrimaryPart.Position) * CFrame.Angles(math.rad(x), math.rad(y), math.rad(z)))
Note: For this to work, PrimaryPart
must not be nil
.
Therefore, we can rotate the hands like this:
longHand:PivotTo(longHandOrigin * CFrame.Angles(0, math.rad(y), 0))
shortHand:PivotTo(shortHandOrigin * CFrame.Angles(0, math.rad(y), 0))
- c. Since we are dealing with time here, you’re gonna use the time of day.
local currentTime = lighting.TimeOfDay
The long hand goes by the minute and since lighting.TimeOfDay
is in the format: hour : minute : seconds (i.e 00:00:00), extract the minutes by getting the substring and convert it to a number.
local currentMinutes = tonumber(string.sub(currentTime, 4, 5))
So now, you can go back to the hands and re-pivot them. But first…
local clock = getTwelveHourClock()
Let me explain what getTwelveHourClock()
does:
if lighting.ClockTime > 12 then
return lighting.ClockTime - 12
else
return lighting.ClockTime
end
getTwelveHourClock()
returns lighting.ClockTime
under these conditions:
- If the current hour (in 24-hour time) is greater than 12, the function will return the difference between
lighting.ClockTime
and 12. - Otherwise, the function will return
lighting.ClockTime
by itself.
So now, we can pivot the hands on its Y-axis. We’ll do this by:
-
(Long Hand): Dividing the current minutes by the number of minutes in an hour. (Short Hand): Dividing the current hour by 12.
-
Multiplying the result by 360 (The full circle angle).
-
Convert it into negative radians. It has to be negative so that it can spin clockwise.
longHand:PivotTo(longHandOrigin * CFrame.Angles(0, -math.rad(360 * currentMinutes/minutesInAnHour), 0))
shortHand:PivotTo(shortHandOrigin * CFrame.Angles(0, -math.rad(360 * clock/12), 0))
Click to see the full script just in case you mess something up
local hands = script.Parent
local longHand = hands:WaitForChild("LongHand")
local shortHand = hands:WaitForChild("ShortHand")
local longHand_Pivot = longHand.PrimaryPart
local shortHand_Pivot = shortHand.PrimaryPart
local lighting = game:GetService("Lighting")
local minutesInAnHour = 60
local longHandOrigin = longHand_Pivot.CFrame
local shortHandOrigin = shortHand_Pivot.CFrame
local function getTwelveHourClock()
if lighting.ClockTime > 12 then
return lighting.ClockTime - 12
else
return lighting.ClockTime
end
end
while wait() do
local currentTime = lighting.TimeOfDay
local currentMinutes = tonumber(string.sub(currentTime, 4, 5))
local clock = getTwelveHourClock()
longHand:PivotTo(longHandOrigin * CFrame.Angles(0, -math.rad(360 * currentMinutes/minutesInAnHour), 0))
shortHand:PivotTo(shortHandOrigin * CFrame.Angles(0, -math.rad(360 * clock/12), 0))
end
Now let’s make a simple day/night cycle.
Just add a server script in ServerScriptService
and:
local lighting = game:GetService("Lighting")
while wait(.05) do -- You can change the rate at which the clock time increases
lighting.ClockTime += .01 -- How much you want to increase the clock time by
end
The final touches
Just to finish up the clock build:
- Add a cylinder in the workspace and name it “Frame”.
- Add another cylinder and name it “Pivot”.
- Resize the cylinder so that the length of the long hand is at least the radius.
- Set the transparency of the pivot of each hand to 1.
- Group the hands, the main pivot and the frame into one model.
- Make sure that all parts are anchored!
**Final result:**
End of tutorial!
And that’s all for this tutorial! If you have any questions, suggestions or feedback, feel free to reply to this topic.