How to make a racing game in Roblox Studio

A track, a car, a countdown and laps that can't be cheated — the parts of a Roblox racing game, the order to build them, and a complete race script.

Updated November 2, 20269 min read

Racing games are short rounds with a clear winner, which makes them easy to understand and easy to replay. The car is only half of it: the race system (start, laps, checkpoints, results) is what turns driving around into a game.

The core loop

Every racing game comes down to one loop that players repeat. Build this first, in grey blocks:

  1. Join the lobby and pick a car
  2. Countdown, then race
  3. Pass every checkpoint, finish the laps
  4. See the results and earn coins for the next car

Systems you need

Track

A closed loop with wide turns, walls or barriers, and invisible checkpoint parts across the road.

Cars

A VehicleSeat that reads the driver's input, plus wheels attached with constraints. The Creator Store has car kits — check every script inside before using one.

Race system

Countdown, a start gate, ordered checkpoints, lap count and finish order — all on the server.

Results and rewards

Coins by finishing position, saved with DataStoreService, spent on new cars or colors.

Leaderboard

Best lap time per player — the number people come back to beat.

Build order

  1. 1

    One car that drives well

    Test the car alone on a flat baseplate first: speed, turning, not flipping. Everything else depends on it feeling good.

  2. 2

    The track

    Block out one loop. Drive it a dozen times and widen every corner where you hit the wall.

  3. 3

    Race script

    Checkpoints and the script below. Test with a local server and two players in Studio.

  4. 4

    Car spawning

    Spawn a car for each racer behind the start gate at the start of a round, and remove it after.

  5. 5

    UI and rewards

    Show the countdown, lap and position; pay coins at the finish.

The key script: Race with countdown, laps and checkpoints

Where it goes: ServerScriptService > Race (Script).

  • In Workspace make a Folder Race with a Folder Checkpoints inside. Add invisible, anchored, CanCollide-off parts across the road named 1, 2, 3… in driving order. 1 is the start/finish line.
  • Add an anchored part StartGate in the Race folder, just behind line 1, blocking the road. Racers line up behind it, so they cross line 1 only after a full lap.
  • Show the status on screen with a LocalScript that reads workspace.Race:GetAttribute("Status").
ServerScriptService > Race (Script)
local Players = game:GetService("Players")

local race = workspace:WaitForChild("Race")
local checkpoints = race:WaitForChild("Checkpoints")
local gate = race:WaitForChild("StartGate")

local LAPS = 3
local MAX_RACE_SECONDS = 300
local COUNT = #checkpoints:GetChildren()

local running = false
local startTime = 0
local progress = {} -- [player] = { next = 2, lap = 0, finished = false }
local finishers = 0

local function status(text)
	race:SetAttribute("Status", text)
end

-- The player touching a checkpoint, on foot or driving a car.
local function playerFromHit(hit)
	local model = hit:FindFirstAncestorOfClass("Model")
	while model do
		local player = Players:GetPlayerFromCharacter(model)
		if player then
			return player
		end
		local seat = model:FindFirstChildWhichIsA("VehicleSeat", true)
		if seat and seat.Occupant then
			return Players:GetPlayerFromCharacter(seat.Occupant.Parent)
		end
		model = model:FindFirstAncestorOfClass("Model")
	end
	return nil
end

for _, part in checkpoints:GetChildren() do
	local index = tonumber(part.Name)
	part.Touched:Connect(function(hit)
		if not running then
			return
		end
		local player = playerFromHit(hit)
		local state = player and progress[player]
		-- Only the next checkpoint counts, so shortcuts don't work.
		if not state or state.finished or index ~= state.next then
			return
		end
		if index == 1 then
			state.lap += 1
			if state.lap >= LAPS then
				state.finished = true
				finishers += 1
				status(string.format("%s finished #%d in %.2f s", player.DisplayName, finishers, os.clock() - startTime))
				return
			end
		end
		state.next = index % COUNT + 1
	end)
end

local function racersLeft()
	local left = 0
	for player, state in progress do
		if player.Parent and not state.finished then
			left += 1
		end
	end
	return left
end

while true do
	running = false
	gate.CanCollide = true
	gate.Transparency = 0.5
	while #Players:GetPlayers() == 0 do
		status("Waiting for players")
		task.wait(2)
	end
	for seconds = 10, 1, -1 do
		status("Race starts in " .. seconds)
		task.wait(1)
	end

	progress, finishers = {}, 0
	for _, player in Players:GetPlayers() do
		progress[player] = { next = 2, lap = 0, finished = false }
	end
	gate.CanCollide = false
	gate.Transparency = 1
	status("GO!")
	startTime = os.clock()
	running = true

	repeat
		task.wait(0.5)
	until racersLeft() == 0 or os.clock() - startTime > MAX_RACE_SECONDS

	running = false
	status("Race over")
	task.wait(8)
end

How it works

  • Checkpoints count only in order, so driving across the grass to line 1 does nothing until the player has passed every checkpoint before it.
  • Times come from the server clock, so a player can't report a faster lap than they drove.
  • Players who join mid-race wait for the next round; players who leave stop counting toward the end of the race.

How racing games make Robux

  • New cars and colors bought with coins earned by racing, with some cosmetic cars for Robux.
  • Cosmetic trails, horns and nameplates.
  • Avoid selling faster cars for Robux in ranked races: paid speed ruins the race for everyone else.

You receive 70% of what players spend on game passes and developer products; Roblox keeps 30%.

Common mistakes

A car that flips at every bump

Lower the car's center of mass (heavier base, lighter top), widen the wheelbase, and keep the track smooth.

Checkpoints players can skip

One finish line with no checkpoints lets players drive backwards over it. Use ordered checkpoints like the script above.

Lap detection on the client

A LocalScript can report any lap time it wants. Count laps and times on the server.

FAQ

How do I make a car in Roblox Studio?

A car is a VehicleSeat on a body, with wheels attached by constraints (for example HingeConstraints set to Motor). The seat's Throttle and Steer values come from the driver; a script turns them into wheel speed and steering. Car kits from the Creator Store are a faster start — check their scripts first.

How do I count laps in a Roblox racing game?

Place numbered checkpoint parts around the track and track each player's next checkpoint on the server. When they cross line 1 after the last checkpoint, add a lap.

How do I stop players from cutting corners in a race?

Only accept checkpoints in order, as this page's script does. A skipped checkpoint means the finish line won't count for that player.

Keep reading