Tutorial · Gameplay

How to make speed pads and jump pads in Roblox Studio

Boost pads make an obby or a race feel fast: step on a green pad and sprint for a few seconds, step on a spring and fly up to the next platform. The two pads work differently. A speed pad changes a Humanoid property, which the server can do. A jump pad pushes the character, and the character is moved by the player's own device, so that one runs in a LocalScript.

Updated 23 October 20265 min readBeginnerLuau

In short

Speed pad: a server Script sets Humanoid.WalkSpeed higher when a player touches a part tagged SpeedPad, remembers the old speed, and puts it back after a few seconds with task.delay. Jump pad: a LocalScript listens to Touched on parts tagged JumpPad and, when the local player's own character touches one, sets the root part's AssemblyLinearVelocity upward.

  • Restore the speed the player had before, not 16, so a game pass speed perk survives.
  • A second touch restarts the boost instead of ending it early: each boost has an id and only the latest one ends it.
  • A server-side velocity change on a character can be overwritten by the player's device, so launch from the client.

Get the script

Speed boost pad script

One Script in ServerScriptService: every part tagged SpeedPad raises WalkSpeed to 40 for 4 seconds, then puts back the speed the player had.

Script in ServerScriptService named SpeedPads
-- Script in ServerScriptService named SpeedPads.
-- Parts tagged "SpeedPad" raise WalkSpeed for a few seconds. Attributes on a pad
-- (Speed, Seconds) override the defaults below.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")

local BOOST_SPEED = 40 -- WalkSpeed while boosted (Roblox's default is 16)
local BOOST_SECONDS = 4

local normalSpeed: { [Humanoid]: number } = {} -- the speed to go back to
local boostId: { [Humanoid]: number } = {} -- so only the latest boost ends it

local function setUpPad(pad: Instance)
	if not pad:IsA("BasePart") then
		return
	end
	pad.Touched:Connect(function(hit: BasePart)
		local character = hit.Parent
		if not (character and character:IsA("Model") and Players:GetPlayerFromCharacter(character)) then
			return
		end
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not humanoid or humanoid.Health <= 0 then
			return
		end
		local speedAttr = pad:GetAttribute("Speed")
		local secondsAttr = pad:GetAttribute("Seconds")
		local speed = if typeof(speedAttr) == "number" then speedAttr else BOOST_SPEED
		local seconds = if typeof(secondsAttr) == "number" then secondsAttr else BOOST_SECONDS

		if normalSpeed[humanoid] == nil then
			normalSpeed[humanoid] = humanoid.WalkSpeed
			humanoid.Destroying:Connect(function()
				normalSpeed[humanoid] = nil
				boostId[humanoid] = nil
			end)
		end
		local id = (boostId[humanoid] or 0) + 1
		boostId[humanoid] = id
		humanoid.WalkSpeed = speed

		task.delay(seconds, function()
			-- A newer pad touch restarted the boost: let that one end it
			if boostId[humanoid] ~= id then
				return
			end
			local before = normalSpeed[humanoid]
			if before then
				humanoid.WalkSpeed = before
			end
			normalSpeed[humanoid] = nil
		end)
	end)
end

for _, pad in CollectionService:GetTagged("SpeedPad") do
	setUpPad(pad)
end
CollectionService:GetInstanceAddedSignal("SpeedPad"):Connect(setUpPad)

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: one Script, then tag your pads
ServerScriptService
  SpeedPads Script new
Workspace
  SpeedPad Part (tag: SpeedPad)

Settings you can change

BOOST_SPEEDIn the script
WalkSpeed during the boost. Roblox's default is 16. A pad with a Number attribute named Speed uses that instead. Default: 40.
BOOST_SECONDSIn the script
How long the boost lasts. A Seconds attribute on a pad overrides it. Default: 4.

For jump pads, use the JumpPads LocalScript in Step 2: a launch has to happen on the player's own device.

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

Add speed pads and jump pads: a Script in ServerScriptService that gives players WalkSpeed 40 for 4 seconds when they touch a part tagged SpeedPad and then restores their previous speed, and a LocalScript that launches the local player upward at 120 studs per second when they touch a part tagged JumpPad.

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

Why the two pads run in different places

Every player's device simulates that player's own character: it runs the physics and sends the result to the server. A property like WalkSpeed set by the server is copied to the device, and the device then walks at that speed, so a speed pad works from a server Script. A push is different. A velocity the server sets on a character can be overwritten by the device's next physics step, so a jump pad works reliably only when the player's own device sets the velocity.

The two pads
PadScriptChanges
Speed padScript in ServerScriptServiceHumanoid.WalkSpeed for a few seconds
Jump padLocalScript in StarterPlayerScriptsAssemblyLinearVelocity of the root part, once

Step 1: Speed pads

  1. Make a flat part, colour it bright green, tick Anchored and tag it SpeedPad (Properties window, Tags, +).
  2. Insert a Script in ServerScriptService named SpeedPads:
Script in ServerScriptService named SpeedPads
-- Script in ServerScriptService named SpeedPads.
-- Parts tagged "SpeedPad" raise WalkSpeed for a few seconds. Attributes on a pad
-- (Speed, Seconds) override the defaults below.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")

local BOOST_SPEED = 40 -- WalkSpeed while boosted (Roblox's default is 16)
local BOOST_SECONDS = 4

local normalSpeed: { [Humanoid]: number } = {} -- the speed to go back to
local boostId: { [Humanoid]: number } = {} -- so only the latest boost ends it

local function setUpPad(pad: Instance)
	if not pad:IsA("BasePart") then
		return
	end
	pad.Touched:Connect(function(hit: BasePart)
		local character = hit.Parent
		if not (character and character:IsA("Model") and Players:GetPlayerFromCharacter(character)) then
			return
		end
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not humanoid or humanoid.Health <= 0 then
			return
		end
		local speedAttr = pad:GetAttribute("Speed")
		local secondsAttr = pad:GetAttribute("Seconds")
		local speed = if typeof(speedAttr) == "number" then speedAttr else BOOST_SPEED
		local seconds = if typeof(secondsAttr) == "number" then secondsAttr else BOOST_SECONDS

		if normalSpeed[humanoid] == nil then
			normalSpeed[humanoid] = humanoid.WalkSpeed
			humanoid.Destroying:Connect(function()
				normalSpeed[humanoid] = nil
				boostId[humanoid] = nil
			end)
		end
		local id = (boostId[humanoid] or 0) + 1
		boostId[humanoid] = id
		humanoid.WalkSpeed = speed

		task.delay(seconds, function()
			-- A newer pad touch restarted the boost: let that one end it
			if boostId[humanoid] ~= id then
				return
			end
			local before = normalSpeed[humanoid]
			if before then
				humanoid.WalkSpeed = before
			end
			normalSpeed[humanoid] = nil
		end)
	end)
end

for _, pad in CollectionService:GetTagged("SpeedPad") do
	setUpPad(pad)
end
CollectionService:GetInstanceAddedSignal("SpeedPad"):Connect(setUpPad)

The first touch of a boost saves the WalkSpeed the player had in normalSpeed. Touched fires many times while a player runs across a pad, so each touch only restarts the timer: boostId goes up by one, and when a timer finishes it only restores the speed if no newer touch happened. When the character is removed, Destroying clears its entries.

This plays well with the sprint script, with one limit: if a player starts sprinting during a boost, the end of the sprint puts back the boosted speed it saw, and the end of the boost then restores the normal speed.

Step 2: Jump pads

  1. Make another part, maybe yellow, Anchored, and tag it JumpPad. For a stronger pad, add a Number attribute Power, such as 200.
  2. Insert a LocalScript in StarterPlayer > StarterPlayerScripts named JumpPads:
LocalScript in StarterPlayerScripts named JumpPads
-- LocalScript in StarterPlayerScripts named JumpPads.
-- Parts tagged "JumpPad" launch the player upward. A "Power" attribute on a pad
-- overrides the default launch speed.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")

local LAUNCH_SPEED = 120 -- studs per second straight up
local COOLDOWN = 0.5 -- seconds before the same player can be launched again

local player = Players.LocalPlayer
local lastLaunch = 0

local function setUpPad(pad: Instance)
	if not pad:IsA("BasePart") then
		return
	end
	-- Touched fires on this device when this player's own character touches the pad
	pad.Touched:Connect(function(hit: BasePart)
		local character = player.Character
		if not character or not hit:IsDescendantOf(character) then
			return
		end
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		local root = humanoid and humanoid.RootPart
		if not (humanoid and root) or humanoid.Health <= 0 then
			return
		end
		local now = os.clock()
		if now - lastLaunch < COOLDOWN then
			return
		end
		lastLaunch = now
		local power = pad:GetAttribute("Power")
		local speed = if typeof(power) == "number" then power else LAUNCH_SPEED
		local v = root.AssemblyLinearVelocity
		-- Keep the sideways speed, replace the vertical speed
		root.AssemblyLinearVelocity = Vector3.new(v.X, speed, v.Z)
		humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
	end)
end

for _, pad in CollectionService:GetTagged("JumpPad") do
	setUpPad(pad)
end
CollectionService:GetInstanceAddedSignal("JumpPad"):Connect(setUpPad)

Touched fires on this device when its own character touches the pad, and the script ignores other players' characters. It keeps the sideways speed and replaces the vertical speed, so a player running onto the pad flies up and forward. Putting the Humanoid into Freefall stops it from treating the launch as walking and cancelling it on the first frame.

At 120 studs per second up, with Roblox's default gravity of 196.2 studs per second squared, a player rises about 37 studs. Raise LAUNCH_SPEED or the pad's Power for higher jumps.

Test it

  1. Press Play and run over the speed pad: you speed up for 4 seconds, then slow back to normal.
  2. Run over it twice in a row: the boost lasts 4 seconds from the second touch.
  3. Step on the jump pad: you are thrown up. Run onto it: you fly up and forward.
  4. In a 2-player test, watch the other player hit a jump pad: you see their launch too.

Common errors and fixes

If a pad does nothing, open the Output window first.

The speed pad does nothing

Check the tag is SpeedPad exactly, the part's CanTouch is ticked, and the script is a Script in ServerScriptService.

The jump pad does nothing, or only sometimes

JumpPads must be a LocalScript in StarterPlayerScripts. A launch set by a server Script often has no effect, because the player's device moves the character.

My speed stays high forever

Another script set WalkSpeed during the boost. Apply permanent speed changes when the character spawns, so a respawn always starts from the right value.

The jump pad launches me twice

Raise COOLDOWN so the second touch as you leave the pad does not count.

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 pads and scripts in your Explorer.

You type

Add green speed pads that make players run at 40 for 4 seconds and yellow jump pads that launch them onto the next platform in my obby.

RoCode does
  • Builds and tags the pads, and writes the speed script on the server and the jump script on the client
  • Reads your place first so the speed pad keeps any speed your other scripts set
  • Is told to compile-check each script with Check Script, and sets undo points around each batch

After a build, RoCode can run its test robot: it plays your game in Studio, walks onto parts and presses keys, and reports PASS or FAIL, for example checking WalkSpeed rose after touching a pad. It checks only what it chose to test. How RoCode connects to Studio.

Questions

How do I make a speed boost pad in Roblox?

In a server Script, raise Humanoid.WalkSpeed when a player touches the pad and restore it with task.delay. Step 1 has a version that handles repeated touches.

Why does my jump pad not work from a server Script?

The player's device simulates their character, so a velocity the server sets can be overwritten. Set it from a LocalScript on that player's device.

Should I use BodyVelocity for a jump pad?

No. Roblox marks BodyVelocity deprecated. For a one-off launch, setting AssemblyLinearVelocity is enough.

How do I make a pad that slows players down?

Use a speed pad with a Speed attribute below 16, such as 8, for mud or sticky floors.

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.