Had this tab sleeping in my browser for a while because the video is cool—
This can be done with model tweens. But you have to take care to tween just the right things, and avoid using Tweens for things that will make you pull your hair out doing complicated vector and cframe math.
Model tweening involves making the model unanchored, but rigidly connected (Welds, WeldConstraint) to an anchored part, which, when tweened, will move the rest of the model. The anchored part’s position is usually chosen carefully to make the tween as simple as possible. In the door example provided in the thread I linked, the door is connected to an invisible part dedicated to being tweened that’s placed where the door hinge would be. This hinge part only moves by rotating around its length, making it significantly easier to tween it. Otherwise, you would get and have to fix funny oddities like this.
Let’s go through a few of the machines in the video.
The pendulums
Let’s do a simple pendulum motion test first.
Open a new place. Add a part. Make it tall and thin. Make sure it’s named Part and there are no others named Part in the workspace, or rename it to something unique and edit the first line of the following script.
Paste this into the command bar, in its entirety (no need to run the game):
local part = workspace.Part
local angle = math.rad(70) -- CFrame angles are usually in radians!
-- Don't uncomment this yet
-- part.CFrame = part.CFrame * CFrame.Angles(0, 0, -angle)
-- The indentation and splitting the function into multiple lines is not required, but helps me add comments
local tween = game.TweenService:Create(
part,
TweenInfo.new(
2, -- The pendulum will go center to center or end to end in 2 seconds, and a full round trip in 4 seconds
Enum.EasingStyle.Sine, -- Important - a pendulum's trajectory follows a sine wave. If you set this to Linear, it will look rather strange. Quad is similar, but not the same.
Enum.EasingDirection.InOut, -- Hard to explain. Set this to In to make it "bounce" against one of its ends, which is not what you want.
-1, -- Amount of times to tween. A negative number means infinite here.
true -- After the tween finishes, return to the starting position
), {
CFrame = part.CFrame * CFrame.Angles(0, 0, angle), -- Tween it to the same position, but a different rotation
-- Don't uncomment this yet
-- CFrame = part.CFrame * CFrame.Angles(0, 0, angle*2),
}
)
-- Make TweenService move the part.
tween:Play()
-- This tween doesn't actually end when the part is gone. If you remove the following, delete the part and undo to get it back, then it will continue to swing. It helps to _always_ be careful with infinitely running tweens.
part.AncestryChanged:Connect(function()
if part.Parent == nil then
tween:Cancel()
end
end)
Your part will now start swinging smoothly. However, it will go from vertical to skewed to vertical, as if gravity were at a 35° angle.
The fix is to skew the part first, to one of its end positions. A tween will change a part from its current state to the target state. I’ve done this for you - uncomment the part.Cframe = ...
line above, see that it’s doing the same thing but in another position, and uncomment the second “don’t uncomment this” line near the bottom to get the intended effect.
Delete the part and undo to make it stop moving and reset position after running these scripts.
The pendulum in the video consists of a cog, chain and ball, all connected rigidly, and swinging about the axle at the top.
Build what you see in the video. Make it all unanchored, but rigid, so that it will fall down when you Run the place, but not fall apart.
Then, have a part whose center point lies exactly on the axle, and whose front face faces the axle exactly. You can pretty much just clone the axle for this. Or it could be one of the parts of the pendulum that’s positioned right, such as the cog.
This pivot part must be anchored, and rigidly connected to the pendulum; when you Run the game, the pendulum should not fall.
Now you can add a Script to the pivot part with the above code, and with workspace.Part
changed to script.Parent
.
Optionally, you can remove the section at the bottom that stops the tween (since stopping the game resets everything anyway)
If the pendulum swings the wrong way - inside to inside not side to side, or just rotates, then change which of the numbers in both of the CFrame.Angles is not 0. Pay attention to the true “facing” of the part. The first number pitches (front moves up-down, nodding), second yaws (part rotates, shaking head) and third rolls. You can also change the angle at the top (70 is in degrees and is converted to radians for use).
You can refer to the documentation to know what order all the parameters are in and why and how to use them.
The drills
Building/modeling the drill is complicated and there are some gotchas involved with tweening 360° rotations.
You need to split the tween up into multiple tweens. This is because tweening CFrame will make the object follow the shortest path that will get it to the target. A 360° rotation ends up in the same place, so tweening an object 360° will make it not move at all.
This post has code showing how to make a part spin.
My own take on it:
local part = workspace.Part
local tweeninfo = TweenInfo.new( -- reused for multiple tweens
1,
Enum.EasingStyle.Linear, -- so it rotates at the same rate constantly. Change this for weird and incorrect results
Enum.EasingDirection.Out -- does not matter for Linear
-- count defaults to 1 and reverse defaults to false, no need to specify them
)
local tween1 = game.TweenService:Create(part, tweeninfo, {CFrame = part.CFrame * CFrame.Angles(0, 0, math.rad(120))})
local tween2 = game.TweenService:Create(part, tweeninfo, {CFrame = part.CFrame * CFrame.Angles(0, 0, math.rad(240))})
local tween3 = game.TweenService:Create(part, tweeninfo, {CFrame = part.CFrame}) -- 360° == 0° :] not an error, just funny
-- Make TweenService move the part.
while part.Parent do
tween1:Play() tween1.Completed:Wait()
tween2:Play() tween2.Completed:Wait()
tween3:Play() tween3.Completed:Wait()
end
As before, model the drill, unanchor it, attach it, pick the right pivot and let it rip.
The large wheels and oil wells
Build them with what you know about making things rotate so far, but skip the crankshafts.
Only the wheel should be tweened.
Make the crankshaft entirely unanchored. Connect the parts with Attachments and Hinge Constraints. The physics solver will do the hard work for you.
The black gloss on everything
Set the Material on everything to SmoothPlastic.
To make the gloss more intense:
Add a ColorCorrectionEffect to Lighting.
Increase Contrast to make the highlights harsher, and decrease Saturation. Either of these can increase past 1 or decrease below -1, there’s a lot of unexplored territory in that regard.
Also avoid using cubical geometry/sharp edges. Cylinders, round surfaces etc. will easily have the highlight somewhere on them.
Optimization. Eliminating network traffic and (less importantly) improving framerate
Eliminating network traffic
It’s vital to take advantage of LocalScripts!!! You should make all the tweens local. After you do that, the crank shafts might stop moving; the solution is to create and attach them using LocalScripts as well.
The reason for this is to avoid having the server send you all the information about how the machines are moving, when their movement is actually perfectly predictable. It also means they can spin around smoothly even when you’re a thousand studs away from them.
improving framerate
You might get away with attaching all the wheels to one pivot/hub and tweening only that, as long as all the wheels are facing the same way and the wheels are on the same axis. This reduces the amount of tweens you have to create. Same with the pendulums, both of the pendulums that swing the same way on the same swing can be attached to one pivot, and all of them can be connected if they’re all lined up. This will leave you with two tweening assemblies: one set of pendulums swinging one way, and another set that’s at the other extreme when the first set is at one extreme.
Extra: The red sky
The Toolbox probably has a good red sky. Failing that, you can fiddle with the ColorCorrection. And if that isn’t an option either, it’s possible to download the images of a close-enough skybox, edit them and reupload.
Misc
If the crank shafts are local, then they might go out of sync with what other players see; climbing them, you may appear to be standing on the air to other players. Tower of Hell has some levels with this same issue.
If the crank shafts are physically simulated and replicated (created on the server, e.g. on load, and not visible only on the client), then exploiters can take control of them and move them around the map, like this:
https://devforum.roblox.com/t/introduction-to-tweening-models/315253/14
The wheels turning, pendulums swinging etc. have no Velocity or RotVelocity, so when you climb them, they slide out from under you and don’t move you out of the way correctly when you’re hit by them.
The RotVelocity on the wheels is simple enough. Consider that Velocity refers to the axis that the object should be rotating around. So if a disk on the ground is spinning, then the Velocity points upward: (0, 10, 0) is 10 radians per second around the Y axis. The wheel code above spins at 120° per second (360° per 3 seconds), so the RotVelocity could be wheel.CFrame.LookVector * math.rad(120)
(or -120). Use LookVector if you’re rotating about Z, RightVector if about X, UpVector if you’re rotating about Y.