TweenService complete guide: TweenInfo, EasingStyles, UI & Parts, chaining tweens
TL;DR
TweenService is the go-to way to animate almost anything in Roblox — parts, UI frames, lights, cameras, you name it. This guide covers the full API: TweenInfo.new() with all six parameters, EasingStyle/Direction combos, animating 3D parts and UI elements, and chaining tweens with the Completed event.
What is TweenService?
TweenService is a built-in service that smoothly interpolates properties of an object from one state to another over a set duration. Instead of manually updating values every frame, you describe what you want to change and how, and the engine handles the rest.
You can animate properties on:
- 3D Parts:
Position,CFrame,Color,Transparency,Size - UI elements:
Position,Size,Rotation,BackgroundTransparency,ImageTransparency - Lights:
Brightness,Color,Range - Sound:
Volume - Camera:
CFrame,FieldOfView
The core API: TweenService:Create(instance, tweenInfo, propertyTable) → Tween
Step 1 — Get the service
Always retrieve TweenService via game:GetService().
local TweenService = game:GetService("TweenService")
Step 2 — Build a TweenInfo
TweenInfo.new() takes six parameters (all optional after the first):
local info = TweenInfo.new(
2, -- 1. Time (seconds)
Enum.EasingStyle.Quad, -- 2. EasingStyle
Enum.EasingDirection.Out, -- 3. EasingDirection
0, -- 4. RepeatCount (0 = play once)
false, -- 5. Reverses (true = ping-pong)
0 -- 6. DelayTime (seconds before start)
)
| # | Parameter | Notes |
|---|---|---|
| 1 | Time | Duration in seconds |
| 2 | EasingStyle | Interpolation curve shape |
| 3 | EasingDirection | In / Out / InOut |
| 4 | RepeatCount | 0 = once; -1 = infinite loop |
| 5 | Reverses | true = plays forward then backward |
| 6 | DelayTime | Wait before each play/repeat |
Important: to loop a tween forever use
RepeatCount = -1. The official Roblox docs explicitly warn against usingmath.huge— it is unstable and may stop working at any point.
Step 3 — EasingStyle & EasingDirection
EasingStyle defines the shape of the curve; EasingDirection defines which end the curve applies to.
EasingStyles
| Style | Feel |
|---|---|
Linear | Constant speed, no easing |
Quad | Gentle ease — great default for UI |
Cubic / Quart / Quint | Increasingly strong acceleration |
Sine | Very smooth sine-wave curve |
Exponential | Extreme acceleration/deceleration |
Elastic | Overshoots then springs back |
Back | Slight overshoot before settling |
Bounce | Simulates a bouncing ball |
EasingDirection
In— slow start, fast endOut— fast start, slow finish (most natural for UI pop-ins)InOut— easing on both ends (best for loops)
Practical tip: Sine + InOut works great for hovering/floating loops. Quart + Out feels snappy and modern for menus sliding in.
Step 4 — Animating a 3D Part
local TweenService = game:GetService("TweenService")
local part = workspace.Part -- must be Anchored
local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
-- Multiple properties can be animated in a single tween —
-- they all start and finish at the same time.
local goals = {
Position = Vector3.new(10, 5, 0),
Color = Color3.fromRGB(255, 100, 50),
}
local tween = TweenService:Create(part, tweenInfo, goals)
tween:Play()
Note: two separate tweens must never target the same property on the same instance — the older one gets cancelled silently by the newer one.
Infinite hover loop
local loopInfo = TweenInfo.new(
1.5,
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut,
-1, -- loop forever
true -- reverse → smooth back-and-forth
)
local hoverTween = TweenService:Create(part, loopInfo, {
Position = part.Position + Vector3.new(0, 3, 0)
})
hoverTween:Play()
Step 5 — Animating UI Elements
For UI, positions and sizes use UDim2, not Vector3. Run this inside a LocalScript.
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local gui = Players.LocalPlayer:WaitForChild("PlayerGui")
local screen = gui:WaitForChild("ScreenGui")
local frame = screen:WaitForChild("Frame")
local slideInfo = TweenInfo.new(0.4, Enum.EasingStyle.Quart, Enum.EasingDirection.Out)
local showTween = TweenService:Create(frame, slideInfo, {
Position = UDim2.new(0.5, 0, 0.5, 0) -- centre of screen
})
local hideTween = TweenService:Create(frame, slideInfo, {
Position = UDim2.new(1.5, 0, 0.5, 0) -- off-screen right
})
showTween:Play()
task.wait(3)
hideTween:Play()
Tip: set AnchorPoint = Vector2.new(0.5, 0.5) before tweening Position or Rotation, so the element pivots from its centre.
Step 6 — Chaining tweens
You can chain UI animations to occur one after another by playing subsequent tweens inside the previous tween's Completed event.
-- Step 1: move label to centre
local moveTween = TweenService:Create(label, info, {
Position = UDim2.new(0.5, 0, 0.5, 0)
})
-- Step 2: rotate 45° once it arrives
local rotateTween = TweenService:Create(label, info, { Rotation = 45 })
moveTween.Completed:Connect(function()
rotateTween:Play()
end)
moveTween:Play()
Alternatively, use Completed:Wait() for linear code in a coroutine:
task.spawn(function()
moveTween:Play()
moveTween.Completed:Wait()
rotateTween:Play()
rotateTween.Completed:Wait()
print("Sequence done!")
end)
Playback controls
| Method | Effect |
|---|---|
tween:Play() | Start or resume |
tween:Pause() | Freeze at current values |
tween:Cancel() | Stop and reset to pre-Play values |
tween.Completed:Wait() | Yield thread until tween ends |
Common pitfalls
- Non-Anchored part + Position tween — physics fights the tween. Anchor the part or tween
CFrameinstead. - UI tweens in a Server Script — UI tweens must live in a LocalScript. Server scripts can't touch
PlayerGui. - Two tweens on the same property — the first is cancelled silently. Call
:Cancel()before starting a replacement. math.hugefor loops — useRepeatCount = -1, notmath.huge. The official docs flag it as unstable.- Tweening
CFrameandPositionat the same time — they conflict. Pick one per tween. - Forgetting
:Play()—TweenService:Create()builds the tween but doesn't start it automatically.
FAQ
Q: Can I tween an entire Model?
Models don't have a single
Position. Tween theCFrameof the model'sPrimaryPart, or callModel:PivotTo()inside a loop. Some community modules (like TweenPlus on GitHub) add native pivot support.
Q: Can I tween a NumberValue?
Yes — any Instance with a tweenable property works, including
NumberValue.Value. This is handy for driving custom logic from a tween curve.
Q: Does running many tweens hurt performance?
TweenService uses the engine's internal scheduler, so it's generally efficient. Tweening hundreds of parts simultaneously can still strain the renderer — batch your tweens or use particles for large-scale effects.
Q: LocalScript vs Script?
Use a LocalScript for visual/UI animations on the client. Use a Script for server-authoritative state (e.g., a shared door) — server tweens replicate through the normal replication pipeline.
If you're building a polished UI system or animated environment and need a head start, the GM Market marketplace has Roblox UI kits and tween-driven effect packs worth browsing.
Drop your questions or share what you've built below! 🎬