In short
Get the service with game:GetService("TweenService"), describe the motion with TweenInfo.new(time, easingStyle, easingDirection), then call TweenService:Create(part, info, { Position = goal }) and :Play() the tween it returns. Any number, Vector3, CFrame, Color3, UDim2 or similar property can be tweened. Use tween.Completed:Wait() to wait for it, and give TweenInfo a repeat count of -1 with reverses on for a back-and-forth loop.
- Tween the part on the server when every player should see it; on the client for effects only that player needs.
- Anchor parts you tween, or physics fights the tween.
- A Model has no Position or CFrame to tween: tween a NumberValue and move the model with
PivotTo.
Get the script
Spinning and floating part script (TweenService)
A Script that makes a part bob up and down and spin forever with two looping tweens, for coins, gems and pickups.
-- Script inside a Part named Gem. Floats up and down and spins forever.
local TweenService = game:GetService("TweenService")
local FLOAT_HEIGHT = 1.5 -- studs above where you placed it
local FLOAT_SECONDS = 1.2 -- each way
local SPIN_SECONDS = 3 -- one full turn
local gem = script.Parent :: BasePart
gem.Anchored = true
local baseCFrame = gem.CFrame
local height = Instance.new("NumberValue")
local angle = Instance.new("NumberValue")
local function apply()
gem.CFrame = baseCFrame * CFrame.new(0, height.Value, 0) * CFrame.Angles(0, math.rad(angle.Value), 0)
end
height.Changed:Connect(apply)
angle.Changed:Connect(apply)
TweenService:Create(height, TweenInfo.new(FLOAT_SECONDS, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true), {
Value = FLOAT_HEIGHT,
}):Play()
TweenService:Create(angle, TweenInfo.new(SPIN_SECONDS, Enum.EasingStyle.Linear, Enum.EasingDirection.In, -1), {
Value = 360,
}):Play()
RoCode builds it in the place you have open in Roblox Studio, on Windows or macOS with a desktop browser; on a phone the button sends the prompt and the link to your computer. Free to start, with free credits every day. More Roblox Studio scripts
Where to put it
Workspace
Gem Part new
FloatingGem Script new
Settings you can change
FLOAT_HEIGHTIn the script- How many studs the part rises above where you placed it. Default:
1.5. SPIN_SECONDSIn the script- Seconds for one full turn. Default:
3.
Tick Anchored on the part. For many gems, use one script and tags as the CollectionService guide shows.
Type-checked with luau-lsp strict against Roblox's API definitions on 5 November 2026. Not playtested in Studio yet: press Play and watch the Output window before you publish.
Prompt for RoCode
Make every part tagged Gem float up and down by 1.5 studs and spin slowly forever using TweenService, from one Script in ServerScriptService.
On this page
The three lines every tween needs
Insert a Part in Workspace, tick Anchored, then hover over it, click + and insert a Script. This moves the part 10 studs up in 2 seconds:
-- Script inside a Part.
local TweenService = game:GetService("TweenService")
local part = script.Parent :: BasePart
local info = TweenInfo.new(2) -- 2 seconds, default easing
local goal = { Position = part.Position + Vector3.new(0, 10, 0) }
local tween = TweenService:Create(part, info, goal)
tween:Play()
The goal is a table of property names and the values they should end at. You can tween several properties at once: { Position = ..., Transparency = 1, Color = Color3.fromRGB(255, 0, 0) }. The tween starts from whatever the values are when you call Play, so you only ever give the end.
| Type | Tweens smoothly? | Examples |
|---|---|---|
| number | Yes | Transparency, Reflectance, a NumberValue's Value |
| Vector3, CFrame | Yes | Position, Size, CFrame, Orientation |
| Color3 | Yes | Color |
| UDim2, Vector2 | Yes | GUI Size and Position |
| boolean, EnumItem | Switches at the end | CanCollide, Material |
| string, Instance | No | Gives cannot be tweened due to type mismatch |
Step 1: Every TweenInfo setting
TweenInfo.new takes up to six values, in this order. You can leave off the ones at the end.
| Value | Default | What it does |
|---|---|---|
time | 1 | Seconds for one play. |
easingStyle | Quad | The shape of the motion: Linear (constant speed), Sine, Quad, Cubic, Back (overshoots), Bounce, Elastic, Exponential. |
easingDirection | Out | Out starts fast and slows down; In starts slow; InOut does both. |
repeatCount | 0 | Extra plays after the first. -1 repeats forever. |
reverses | false | Play back to the start after each play. |
delayTime | 0 | Seconds to wait before starting. |
-- Script inside a Part named Platform.
-- Slides back and forth 12 studs forever, easing at both ends.
local TweenService = game:GetService("TweenService")
local platform = script.Parent :: BasePart
local info = TweenInfo.new(
3, -- seconds each way
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut,
-1, -- repeat forever
true -- come back each time
)
TweenService:Create(platform, info, { Position = platform.Position + Vector3.new(12, 0, 0) }):Play()
For a platform that should carry players standing on it, a tweened anchored part moves under them but does not take them along. The moving platform guide covers that case.
Step 2: Rotate, resize and fade
To rotate, tween CFrame to the current CFrame times a rotation. Tweening Orientation also works, but CFrame keeps the part in place while it turns. Here a wall fades and shrinks when the script runs, then is removed once the tween finishes:
-- Script inside a Part named FadingWall.
local TweenService = game:GetService("TweenService")
local wall = script.Parent :: BasePart
-- turn a quarter around the part's own up axis in 1 second
local turn = TweenService:Create(wall, TweenInfo.new(1), {
CFrame = wall.CFrame * CFrame.Angles(0, math.rad(90), 0),
})
turn:Play()
turn.Completed:Wait() -- carry on only once it has finished
-- then fade out and shrink at the same time
local fade = TweenService:Create(wall, TweenInfo.new(0.8, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
Transparency = 1,
Size = wall.Size * 0.2,
})
fade:Play()
fade.Completed:Wait()
wall:Destroy()
Completed fires with a PlaybackState: Completed when it reached the goal, or Cancelled when tween:Cancel() stopped it. Do not wait on Completed for a tween that repeats forever: it never finishes.
Step 3: A floating, spinning pickup
Two looping tweens on different properties run side by side. Tweening a full 360 degrees with CFrame does nothing, because the start and the end are the same rotation, so the spin tweens a NumberValue from 0 to 360 and sets the CFrame from it. Put this Script inside an anchored part:
-- Script inside a Part named Gem. Floats up and down and spins forever.
local TweenService = game:GetService("TweenService")
local FLOAT_HEIGHT = 1.5 -- studs above where you placed it
local FLOAT_SECONDS = 1.2 -- each way
local SPIN_SECONDS = 3 -- one full turn
local gem = script.Parent :: BasePart
gem.Anchored = true
local baseCFrame = gem.CFrame
local height = Instance.new("NumberValue")
local angle = Instance.new("NumberValue")
local function apply()
gem.CFrame = baseCFrame * CFrame.new(0, height.Value, 0) * CFrame.Angles(0, math.rad(angle.Value), 0)
end
height.Changed:Connect(apply)
angle.Changed:Connect(apply)
TweenService:Create(height, TweenInfo.new(FLOAT_SECONDS, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true), {
Value = FLOAT_HEIGHT,
}):Play()
TweenService:Create(angle, TweenInfo.new(SPIN_SECONDS, Enum.EasingStyle.Linear, Enum.EasingDirection.In, -1), {
Value = 360,
}):Play()
The spin uses Linear easing so it turns at a steady speed, and it restarts at 0 each loop, which is the same angle as 360, so there is no jump. The coin collect guide puts pickups like this into a game.
Step 4: Tween a whole Model
A Model has no Position or CFrame property, so TweenService:Create(model, ...) has nothing to move. Tween a NumberValue from 0 to 1 instead and move the model with PivotTo, which moves every part inside it together:
-- Script inside a Model named Elevator.
-- Moves the whole model 20 studs up and back, every part together.
local TweenService = game:GetService("TweenService")
local elevator = script.Parent :: Model
local startPivot = elevator:GetPivot()
local endPivot = startPivot * CFrame.new(0, 20, 0)
local progress = Instance.new("NumberValue")
progress.Changed:Connect(function(alpha: number)
elevator:PivotTo(startPivot:Lerp(endPivot, alpha))
end)
local info = TweenInfo.new(4, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, -1, true, 2)
TweenService:Create(progress, info, { Value = 1 }):Play()
Anchor every part of the model. The 2 at the end of TweenInfo is the delay before each play, so the elevator waits at the top and the bottom. The door guide uses the same pattern to swing doors made of several parts.
Server or client?
A tween played in a server Script changes the part on the server, and the new values replicate to every player, so everyone sees it. A tween in a LocalScript changes the part only on that player's screen.
| Play it in | When | Example |
|---|---|---|
| A server Script | The change matters to the game or to everyone. | Doors, moving obstacles, a bridge that opens |
| A LocalScript | Only this player should see it, or it is purely a visual effect. | A pickup fading for the player who collected it, UI |
Replication sends updates many times a second, so server tweens look smooth to most players, but very fast or very many server tweens can look less smooth on slow connections. For lots of decorative motion (hundreds of spinning coins), play the tweens in a LocalScript on each client.
Common errors and fixes
Open the Output window (Window menu, then Output) before you press Play.
The part does not move at all
Check that you called :Play() on the tween, that the goal property name is spelled exactly (Position, not position), and that it is a Script in a place where scripts run (inside a part in Workspace, or ServerScriptService).
The part falls or shakes while tweening
It is not anchored, so gravity and collisions fight the tween. Tick Anchored.
TweenService:Create property cannot be tweened due to type mismatch
The goal value is the wrong type, for example a number for a Vector3 property. See the error page.
Unable to cast to Dictionary or Unable to cast value to Object
The arguments are in the wrong order or the wrong type. It is always Create(instance, tweenInfo, goalTable). See Unable to cast value to Object.
Build it with RoCode
If you would rather not write tweens by hand, RoCode can build them in the place you have open. RoCode is an independent AI agent for Roblox Studio, not made by Roblox: you describe the change in a web chat, and its Studio plugin creates the scripts in your Explorer, so there is no code to paste.
Make the bridge model in Workspace slide 15 studs to the side when the round starts, using a NumberValue tween and PivotTo, and fade the red barrier parts out over 1 second at the same time.
- Can find the parts and models you mean with Search Game before it writes anything
- Writes the Script with Create Script and is told to compile-check it with Check Script
- Sets an undo point before and after each batch of changes, so Ctrl+Z steps back one batch at a time
With plugin 3.9 or newer RoCode can run a short playtest and read the errors, but motion is easiest to judge with your own eyes, so press Play and watch it. How RoCode connects to Studio.
Questions
How do I use TweenService in Roblox?
Get the service, make a TweenInfo, call TweenService:Create(object, info, { Property = goal }) and :Play() the result. The first section has a three-line example.
How do I make a tween loop forever?
Pass -1 as the fourth value of TweenInfo.new (repeatCount), and true as the fifth if it should go back and forth.
How do I wait for a tween to finish?
Call tween.Completed:Wait() after tween:Play(), or connect a function to tween.Completed.
Can I tween a Model?
Not directly. Tween a NumberValue from 0 to 1 and call model:PivotTo(start:Lerp(goal, value)) when it changes, as in Step 4.
How do I stop a tween?
Call tween:Cancel() to stop and leave the part where it is, or tween:Pause() to resume later with Play().
Sources and further reading
- Roblox Creator Docs: TweenService. Create, tweenable types and cancelling
- Roblox Creator Docs: TweenInfo
- Roblox Creator Docs: Tween. Play, Pause, Cancel and Completed
- Roblox Creator Docs: UI animation and tweens. easing styles and directions, shown on UI
- Roblox Creator Docs: PVInstance:PivotTo
How the code was checked: every script on this page passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 5 November 2026). A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.