Tutorial · Gameplay

How to make a moving platform in Roblox Studio

The first moving platform most people make is an anchored part moved by TweenService, and the first thing they notice is that players slide off it. An anchored part that is moved by changing its position has no speed in the physics engine, so it does not carry what stands on it. This guide moves an unanchored platform with physics constraints instead, so characters ride it.

Updated 23 October 20265 min readIntermediateLuau

In short

Make the platform an unanchored part. In a Script inside it, add an Attachment, an AlignPosition in OneAttachment mode with MaxVelocity set to the speed you want, and an AlignOrientation holding its starting rotation. Switch the AlignPosition's Position between the start and the end. Physics moves the platform at a steady speed, and characters on it move with it.

  • An anchored part moved by TweenService or CFrame does not carry players; an unanchored one moved by physics does.
  • MaxVelocity sets the speed, so the platform travels at a constant pace instead of snapping.
  • Give the server network ownership, so the platform does not stutter as players come and go.

Get the script

Moving platform script that carries players

A Script inside a part that moves it back and forth with AlignPosition and AlignOrientation, so players standing on it ride along.

Script in the platform part named MovingPlatform
-- Script inside a platform part, named MovingPlatform.
-- Moves the platform back and forth with physics, so players standing on it ride
-- along. Set a Vector3 attribute "Travel" on the part, e.g. 0, 0, 30 for 30 studs along Z.
local SPEED = 8 -- studs per second
local PAUSE_SECONDS = 2 -- wait at each end

local platform = script.Parent :: BasePart
local travelAttr = platform:GetAttribute("Travel")
local travel = if typeof(travelAttr) == "Vector3" then travelAttr else Vector3.new(0, 0, 30)

local startCFrame = platform.CFrame
local startPosition = startCFrame.Position
local endPosition = startPosition + travel

-- The platform is moved by physics, not by changing its position, so it must not be anchored
platform.Anchored = false

local attachment = Instance.new("Attachment")
attachment.Parent = platform

-- AlignPosition pulls the platform toward a point, at no more than SPEED
local mover = Instance.new("AlignPosition")
mover.Mode = Enum.PositionAlignmentMode.OneAttachment
mover.Attachment0 = attachment
mover.Position = startPosition
mover.MaxVelocity = SPEED
mover.MaxForce = math.huge
mover.Responsiveness = 200
mover.Parent = platform

-- AlignOrientation keeps it flat and stops it from spinning
local holder = Instance.new("AlignOrientation")
holder.Mode = Enum.OrientationAlignmentMode.OneAttachment
holder.Attachment0 = attachment
holder.CFrame = startCFrame.Rotation
holder.MaxTorque = math.huge
holder.Responsiveness = 200
holder.Parent = platform

-- The server always moves it, so it does not stutter when a different player gets near
platform:SetNetworkOwner(nil)

local distance = travel.Magnitude
local target = endPosition
while true do
	mover.Position = target
	-- Wait about as long as the trip takes, then pause
	task.wait(distance / SPEED + PAUSE_SECONDS)
	target = if target == endPosition then startPosition else endPosition
end

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

Explorer: a Script inside the platform part
Workspace
  Platform Part (Travel attribute)
    MovingPlatform Script new

Settings you can change

SPEEDIn the script
Studs per second. Default: 8.
PAUSE_SECONDSIn the script
Wait at each end. Default: 2.
TravelAttribute
A Vector3 attribute on the part: how far and which way it moves from where you placed it. Default: 0, 0, 30.

The script unanchors the platform. Nothing else may be welded to it unless it should move too.

Type-checked with luau-lsp strict against Roblox's API definitions on 23 October 2026. Not playtested in Studio yet: press Play and watch the Output window before you publish.

Prompt for RoCode

Make this part a moving platform that players can ride: a Script inside it that unanchors it, moves it back and forth 30 studs along Z at 8 studs per second with AlignPosition in OneAttachment mode and MaxVelocity, keeps it level with AlignOrientation, pauses 2 seconds at each end and gives the server network ownership.

On this page
  1. Get the script
  2. How it works
  3. 1. Script
  4. Variations
  5. Common errors
  6. With RoCode
  7. Questions
  8. Sources

Why players slide off tweened platforms

Roblox's physics moves what stands on a part using that part's velocity. An anchored part moved by TweenService is moved by setting its position every frame: it gets to the new place, but its velocity stays zero, so a character on it is not carried, and on a fast tween can fall through or be left behind. An unanchored part moved by a constraint really moves, with a velocity, and carries characters with friction like a real floor.

Ways to move a platform
ApproachCarries players?Notes
Anchored part, TweenService on CFrameNot reliablyFine for things nobody stands on: doors, lava, decorations.
Unanchored part, AlignPosition with MaxVelocity (this guide)YesConstant speed, any direction, simple to set up in code.
Unanchored part, PrismaticConstraint with a ServoYesSlides along one axis between limits; set up with attachments in Studio.

Step 1: The platform script

  1. Insert a Part about 10, 1, 10 where the platform should start. It can be anchored while you build: the script unanchors it.
  2. Add an attribute: Attributes, +, name Travel, type Vector3, value such as 0, 0, 30 (30 studs along Z) or 0, 20, 0 for a lift.
  3. Insert a Script inside the part named MovingPlatform:
Script in the platform part named MovingPlatform
-- Script inside a platform part, named MovingPlatform.
-- Moves the platform back and forth with physics, so players standing on it ride
-- along. Set a Vector3 attribute "Travel" on the part, e.g. 0, 0, 30 for 30 studs along Z.
local SPEED = 8 -- studs per second
local PAUSE_SECONDS = 2 -- wait at each end

local platform = script.Parent :: BasePart
local travelAttr = platform:GetAttribute("Travel")
local travel = if typeof(travelAttr) == "Vector3" then travelAttr else Vector3.new(0, 0, 30)

local startCFrame = platform.CFrame
local startPosition = startCFrame.Position
local endPosition = startPosition + travel

-- The platform is moved by physics, not by changing its position, so it must not be anchored
platform.Anchored = false

local attachment = Instance.new("Attachment")
attachment.Parent = platform

-- AlignPosition pulls the platform toward a point, at no more than SPEED
local mover = Instance.new("AlignPosition")
mover.Mode = Enum.PositionAlignmentMode.OneAttachment
mover.Attachment0 = attachment
mover.Position = startPosition
mover.MaxVelocity = SPEED
mover.MaxForce = math.huge
mover.Responsiveness = 200
mover.Parent = platform

-- AlignOrientation keeps it flat and stops it from spinning
local holder = Instance.new("AlignOrientation")
holder.Mode = Enum.OrientationAlignmentMode.OneAttachment
holder.Attachment0 = attachment
holder.CFrame = startCFrame.Rotation
holder.MaxTorque = math.huge
holder.Responsiveness = 200
holder.Parent = platform

-- The server always moves it, so it does not stutter when a different player gets near
platform:SetNetworkOwner(nil)

local distance = travel.Magnitude
local target = endPosition
while true do
	mover.Position = target
	-- Wait about as long as the trip takes, then pause
	task.wait(distance / SPEED + PAUSE_SECONDS)
	target = if target == endPosition then startPosition else endPosition
end

AlignPosition in OneAttachment mode pulls the platform's attachment toward the point in its Position property, never faster than MaxVelocity. MaxForce is unlimited so players' weight cannot hold it down. AlignOrientation holds the starting rotation, so the platform stays level when a player lands on one edge. The loop switches the target, waits for the trip plus the pause, and switches back.

SetNetworkOwner(nil) keeps the server simulating the platform. Otherwise Roblox may hand an unanchored part to the device of a nearby player, and the handover can make the platform jump. Roblox's network ownership page suggests this for gameplay-critical parts, and also says to use it conservatively, since it can make physics feel less smooth for players.

Lifts, loops and timing

  • A lift: set Travel to 0, 20, 0. AlignPosition holds it up against gravity, so it works vertically too.
  • A route with more stops: replace the two points with a list of positions and step through it.
  • A platform that waits for a player: start the loop only after a Touched from a character, as in a teleporter pad.
  • Many platforms: copy the part with the Script inside. Each one reads its own Travel attribute.

Test it

  1. Press Play. The platform moves 30 studs, pauses 2 seconds and comes back.
  2. Jump on and stand still: you ride along without walking.
  3. Walk around on it while it moves: you stay on.
  4. Set Travel to 0, 20, 0 and ride it up as a lift.

Common errors and fixes

If the platform does not move, check the Output window first.

The platform falls

The constraints are missing or too weak. Check nothing else deletes the attachment, and that the script is a Script inside the part.

The platform tilts when I land on it

AlignOrientation holds the rotation; if it still tilts, raise its Responsiveness. Also check the part is not welded to something heavy.

Players still slide off

The part is anchored again, or something else moves it with CFrame. Only the constraints may move it.

It goes too far or not far enough

Travel is measured from where the part starts in Studio. Check the attribute is a Vector3, not a string.

Build it with RoCode

If you would rather not set this up by hand, RoCode can build it 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 parts and scripts in your Explorer.

You type

Add three moving platforms across the lava gap in my obby that players can ride, moving 25 studs back and forth at different speeds, and a lift at the end that goes up 20 studs.

RoCode does
  • Builds the platforms and writes the platform script with each one's Travel and speed
  • Is told to compile-check each script with Check Script, and sets undo points around each batch
  • Can build a themed world island around your course in one call

After a build, RoCode can run its test robot: it plays your game in Studio, walks and jumps, and reports PASS or FAIL. It checks only what it chose to test, so ride the platforms yourself. How RoCode connects to Studio.

Questions

How do I make a moving platform players can stand on?

Move an unanchored part with physics, for example AlignPosition with MaxVelocity, instead of tweening an anchored part. Step 1 has the script.

Why do I slide off my TweenService platform?

A tweened anchored part has no velocity in the physics engine, so it does not carry what stands on it.

Can I use a PrismaticConstraint instead?

Yes. A PrismaticConstraint with its ActuatorType set to Servo slides a part between two attachments, and players ride it the same way.

Does the platform work in a live game with many players?

Yes. The server simulates it and every player sees the same movement.

Sources and further reading

How the code was checked: every script on this page passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 23 October 2026). A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.

Try RoCode on your own place.

Free every day, no card required. Install the plugin, describe the feature, and review what lands in Studio.