Skip to main content

Stage 2: Sphere Staircase + jump pad

Course progressStage 2 of 10
~35 min
Before you start

Make sure Stage 1 works and resetting brings you back to the red Stage 2 checkpoint.

Build

a sphere staircase and a Stage 3 checkpoint

Learn

how a tiny script can give a player a short upward push

Ship

a jump pad that makes the obby feel like parkour

The big idea

A jump pad is simple magic: touch the pad, get pushed upward for a tiny moment. Students see the result immediately, so the code feels worth typing.

New words
Touched
an event that runs when something bumps into a part
HumanoidRootPart
the center part Roblox uses to move a character
velocity
speed in a direction

Build it

Step 1 — Build the sphere staircase

Add 5 anchored Ball parts after the Stage 2 checkpoint. Make each sphere a little higher and farther than the last.

  • Name them SphereStep_1 through SphereStep_5.
  • Keep them big enough to land on.
  • Use bright colors so the path is easy to read.

Press Play and jump across them.

Step 2 — Build the jump pad

Add one part after the spheres:

Build this part

JumpPad_1

Block
Open recipe
Size
8 × 1 × 8
Color
Cyan
Material
Neon
Anchored
✓ Yes
Place
After the last sphere, before a small gap
Target
JumpPadTarget

Add one small marker part where the jump pad should send the player:

Build this part

JumpPadTarget

Block
Open recipe
Size
2 × 1 × 2
Color
Bright yellow
Material
Neon
Anchored
✓ Yes
Place
On the landing side of the gap

Make JumpPadTarget transparent if you want it hidden.

Before you script the pad, add one RemoteEvent:

  • In ReplicatedStorage, insert a RemoteEvent.
  • Name it LaunchPlayer.

Now add one client launcher script:

  • In StarterPlayer > StarterPlayerScripts, insert a LocalScript.
  • Name it ParkourLaunchClient.
  • Paste this code:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = Players.LocalPlayer
local launchEvent = ReplicatedStorage:WaitForChild("LaunchPlayer")

launchEvent.OnClientEvent:Connect(function(launch)
local character = player.Character or player.CharacterAdded:Wait()
local root = character:FindFirstChild("HumanoidRootPart")
if not root then return end

root:ApplyImpulse(launch * root.AssemblyMass)
end)

Insert a Script inside JumpPad_1:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local pad = script.Parent
local target = workspace:WaitForChild("JumpPadTarget")
local launchEvent = ReplicatedStorage:WaitForChild("LaunchPlayer")
local FORWARD_POWER = 35
local JUMP_POWER = 100
local cooldown = {}

pad.Touched:Connect(function(hit)
local character = hit.Parent
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root then return end

local player = Players:GetPlayerFromCharacter(character)
if not player or cooldown[player] then return end

cooldown[player] = true

local direction = target.Position - pad.Position
local flatDirection = Vector3.new(direction.X, 0, direction.Z)
local launch = Vector3.new(0, JUMP_POWER, 0)

if flatDirection.Magnitude > 0 then
launch = launch + flatDirection.Unit * FORWARD_POWER
end

launchEvent:FireClient(player, launch)

task.delay(0.3, function()
cooldown[player] = nil
end)
end)

Press Play. Step on the pad and watch your character blast upward. The first test should feel obvious.

Step 3 — Add the Stage 3 checkpoint

Place a new SpawnLocation where the jump pad lands. Set it to a new color, add StageNumber = 3, and create the matching Stage 3 Team. Give this checkpoint the same settings as Stage 1 (check AllowTeamChangeOnTouch, uncheck Neutral, match the pad's TeamColor to its Team), and uncheck AutoAssignable on the new Team so players always start at Stage 1.

Understand it

The pad waits for a player to touch it. Then it finds the player's HumanoidRootPart and adds a short upward push toward JumpPadTarget.

The Script inside the pad decides when a launch should happen and sends the launch direction to LaunchPlayer. The LocalScript receives that message on the player's computer and calls ApplyImpulse on the player's own character. That matters because Roblox often lets the client own character physics. The script reads the direction from the pad to JumpPadTarget, so rotating the pad does not change the launch.

The important idea is not the long Roblox word. The idea is: touch part -> change motion.

Try this

Learning beat

Try this

Three short experiments. Predict before you run, then test your guess.

Predict first

What will happen if JUMP_POWER changes from 100 to 50?

Compare

Test JUMP_POWER at 80, 100, and 120. Which launch feels exciting but still controllable?

Connect

Where else could a touch part change how the player moves?

Test your stage

  • The sphere staircase is possible.
  • LaunchPlayer exists in ReplicatedStorage.
  • ParkourLaunchClient exists in StarterPlayerScripts.
  • The jump pad launches upward and toward JumpPadTarget.
  • The landing checkpoint has StageNumber = 3.
  • Resetting after touching Stage 3 brings you back there.

If it breaks

  • Nothing happens on the pad. Make sure the Script is inside JumpPad_1.
  • The pad sees me but I do not launch. Check that LaunchPlayer is in ReplicatedStorage and ParkourLaunchClient is in StarterPlayerScripts.
  • The launch goes to the wrong place. Move JumpPadTarget; do not rotate the pad to aim.
  • The launch is too weak. Raise JUMP_POWER.
  • The launch is too wild. Lower JUMP_POWER or move the landing closer.
  • The pad fires again and again. Check that cooldown[player] = true, task.delay(0.3, ...), and cooldown[player] = nil are all in the script.
Coach notes

Do not over-explain velocity. Let students tune the number and feel the difference. The number-feel connection is the win.