Tutorial · Rewards

How to make collectable coins in Roblox Studio

Coins scattered around a map are the first reward loop most Roblox games add: walk over one, hear the count go up, watch it come back later. This guide builds it with one server script for every coin in your game, a Coins column in the player list, and a spin that runs on each player's screen so the server stays free for gameplay.

Updated 23 October 20266 min readBeginnerLuau

In short

Tag every coin part Coin. One Script in ServerScriptService creates a leaderstats folder with a Coins IntValue for each player, connects Touched on every tagged part, adds to Coins when a living player touches it, then hides the coin (Transparency = 1, CanTouch = false) and brings it back after a delay.

  • The server adds the coins. A LocalScript that changes Coins only changes that player's own screen.
  • A collected flag per coin stops one touch from paying several times: Touched fires once per touching body part.
  • Spin the coins in a LocalScript, so the server does not move dozens of parts every frame.

Get the script

Coin pickup script with respawn

One Script in ServerScriptService: every part tagged Coin adds to the Coins leaderstat when touched, hides, and comes back after 10 seconds.

Script in ServerScriptService named CoinPickups
-- Script in ServerScriptService named CoinPickups.
-- Every part tagged "Coin" gives coins when a player touches it, hides, then comes back.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")

local COIN_VALUE = 1 -- coins per pickup (a coin part can override it with a "Value" attribute)
local RESPAWN_SECONDS = 10 -- how long a collected coin stays hidden

-- leaderstats: the Coins column in the player list
Players.PlayerAdded:Connect(function(player: Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Value = 0
	coins.Parent = leaderstats
	leaderstats.Parent = player
end)

local function addCoins(player: Player, amount: number)
	local leaderstats = player:FindFirstChild("leaderstats")
	local coins = leaderstats and leaderstats:FindFirstChild("Coins")
	if coins and coins:IsA("IntValue") then
		coins.Value += amount
	end
end

local function setUpCoin(coin: Instance)
	if not coin:IsA("BasePart") then
		return
	end
	local collected = false
	coin.Touched:Connect(function(hit: BasePart)
		if collected then
			return
		end
		local character = hit.Parent
		if not (character and character:IsA("Model")) then
			return
		end
		local player = Players:GetPlayerFromCharacter(character)
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not (player and humanoid and humanoid.Health > 0) then
			return
		end
		collected = true
		local value = coin:GetAttribute("Value")
		addCoins(player, if typeof(value) == "number" then value else COIN_VALUE)

		-- Hide the coin for everyone, then bring it back
		local oldTransparency = coin.Transparency
		coin.Transparency = 1
		coin.CanTouch = false
		task.delay(RESPAWN_SECONDS, function()
			coin.Transparency = oldTransparency
			coin.CanTouch = true
			collected = false
		end)
	end)
end

for _, coin in CollectionService:GetTagged("Coin") do
	setUpCoin(coin)
end
CollectionService:GetInstanceAddedSignal("Coin"):Connect(setUpCoin)

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 coins
ServerScriptService
  CoinPickups Script new
Workspace
  Coin Part (tag: Coin)

Settings you can change

COIN_VALUEIn the script
Coins per pickup. A coin part with a number attribute named Value pays that instead. Default: 1.
RESPAWN_SECONDSIn the script
How long a collected coin stays hidden before it can be collected again. Default: 10.

If another script already creates leaderstats (the leaderboard guide, for example), delete the PlayerAdded part of this one and keep a single source of the folder.

What a cheater can and cannot doA cheater can teleport their character onto every coin, so they collect faster than walking allows, but they cannot add coins without touching one: the server adds them. For a big economy, also rate-limit pickups per player on the server.

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 collectable coins to my game: one Script in ServerScriptService that gives every player a Coins leaderstat, makes every part tagged Coin add 1 coin when a living player touches it, hides the coin for 10 seconds and then brings it back, plus a LocalScript that spins the coins.

On this page
  1. Get the script
  2. How it works
  3. 1. The coin
  4. 2. Pickup script
  5. 3. Spin
  6. 4. Saving
  7. Common errors
  8. With RoCode
  9. Questions
  10. Sources

How coin pickups work

A coin is any part with the Coin tag. The server watches each one for Touched. When a body part of a living player touches it, the server adds to that player's Coins and hides the coin for everyone. Changes the server makes, to the Coins value and to the coin's transparency, reach every player automatically.

The pieces
PieceWhereJob
Coin partsWorkspace, tagged CoinAnything round and gold: a Cylinder part turned on its side works.
CoinPickups ScriptServerScriptServiceCreates leaderstats, pays out, hides and respawns coins.
CoinSpin LocalScriptStarterPlayerScriptsSpins every coin on each player's screen.

Step 1: Make a coin and tag it

  1. Insert a Part, set its Shape to Cylinder, its size to about 0.5, 3, 3, its colour to gold and its Material to Neon or Metal.
  2. Tick Anchored, and untick CanCollide so players walk through it instead of bumping into it. Leave CanTouch ticked.
  3. In the Properties window, under Tags, click + and type Coin.
  4. Duplicate it (Ctrl+D) and spread copies around the map. Tags are copied too.
  5. For a big coin worth more, add an attribute: Attributes, +, name Value, type Number, value 10.

Step 2: Add the pickup script

Hover over ServerScriptService, click +, insert a Script named CoinPickups and paste this:

Script in ServerScriptService named CoinPickups
-- Script in ServerScriptService named CoinPickups.
-- Every part tagged "Coin" gives coins when a player touches it, hides, then comes back.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")

local COIN_VALUE = 1 -- coins per pickup (a coin part can override it with a "Value" attribute)
local RESPAWN_SECONDS = 10 -- how long a collected coin stays hidden

-- leaderstats: the Coins column in the player list
Players.PlayerAdded:Connect(function(player: Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Value = 0
	coins.Parent = leaderstats
	leaderstats.Parent = player
end)

local function addCoins(player: Player, amount: number)
	local leaderstats = player:FindFirstChild("leaderstats")
	local coins = leaderstats and leaderstats:FindFirstChild("Coins")
	if coins and coins:IsA("IntValue") then
		coins.Value += amount
	end
end

local function setUpCoin(coin: Instance)
	if not coin:IsA("BasePart") then
		return
	end
	local collected = false
	coin.Touched:Connect(function(hit: BasePart)
		if collected then
			return
		end
		local character = hit.Parent
		if not (character and character:IsA("Model")) then
			return
		end
		local player = Players:GetPlayerFromCharacter(character)
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not (player and humanoid and humanoid.Health > 0) then
			return
		end
		collected = true
		local value = coin:GetAttribute("Value")
		addCoins(player, if typeof(value) == "number" then value else COIN_VALUE)

		-- Hide the coin for everyone, then bring it back
		local oldTransparency = coin.Transparency
		coin.Transparency = 1
		coin.CanTouch = false
		task.delay(RESPAWN_SECONDS, function()
			coin.Transparency = oldTransparency
			coin.CanTouch = true
			collected = false
		end)
	end)
end

for _, coin in CollectionService:GetTagged("Coin") do
	setUpCoin(coin)
end
CollectionService:GetInstanceAddedSignal("Coin"):Connect(setUpCoin)

A folder named exactly leaderstats inside a player makes Roblox show its values as columns in the player list, so Coins appears in the top-right corner. When a coin is touched, the script checks the part belongs to a living player's character, sets collected so the other body parts touching the same frame do not pay again, and adds the coin's value.

Hiding uses Transparency = 1 and CanTouch = false, which keeps the coin in place for its return. task.delay runs the respawn later without stopping the script.

Step 3: Spin the coins

A spinning coin is easier to spot. Spinning dozens of parts on the server every frame would send all those moves to every player, so this LocalScript spins them on each player's own screen instead. Insert it in StarterPlayer > StarterPlayerScripts.

LocalScript in StarterPlayerScripts named CoinSpin
-- LocalScript in StarterPlayerScripts named CoinSpin.
-- Spins every coin on each player's own screen, so the server does no work for it.
local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")

local SPIN_DEGREES_PER_SECOND = 90

RunService.RenderStepped:Connect(function(deltaTime: number)
	local turn = CFrame.Angles(0, math.rad(SPIN_DEGREES_PER_SECOND * deltaTime), 0)
	for _, coin in CollectionService:GetTagged("Coin") do
		if coin:IsA("BasePart") and coin.Anchored then
			coin.CFrame = coin.CFrame * turn
		end
	end
end)

A rotation a LocalScript makes stays on that device, which is fine here: the coin's spot is the same for everyone, only its turn differs.

Step 4: Save the coins

Coins reset when the player leaves until you save them. The DataStore guide saves leaderstats between sessions, and the leaderboard guide's saving step does the same for a Coins column. Once coins save, spend them in a shop or on eggs.

Test it

  1. Press Play. The player list shows Coins: 0.
  2. Walk through a coin. Coins goes up by 1 (or the coin's Value) and the coin disappears.
  3. Wait 10 seconds: the coin is back. Walk through it again.
  4. Start a 2-player test (Test tab, Clients and Servers, 2 players). A coin one player takes disappears for the other too.

Common errors and fixes

Most problems show in the Output window (Window menu, then Output).

Coins does not show in the player list

The folder must be named exactly leaderstats, all lower case, and be a child of the Player. Check two scripts are not both creating it.

Touching a coin does nothing

Check the tag is Coin with a capital C, the part's CanTouch is ticked and the script is a Script in ServerScriptService.

One coin gives several coins

Without the collected flag, each body part that touches pays again. Use the script as written.

The coins do not spin

CoinSpin must be a LocalScript in StarterPlayerScripts, and it only spins anchored coins.

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

Scatter 30 spinning gold coins around my map that add to a Coins leaderstat, disappear when collected and come back after 10 seconds, and save Coins between sessions.

RoCode does
  • Builds the coin parts, tags them and writes the pickup and spin scripts
  • Reads your place first, so it reuses a leaderstats script you already have instead of making a second one
  • Is told to compile-check each script it writes 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 into parts and reports PASS or FAIL, for example walking onto a coin and checking Coins went up. It checks only what it chose to test, so play it yourself too. How RoCode connects to Studio.

Questions

How do I make a coin you can collect in Roblox?

Tag a part Coin and use one server Script that adds to a Coins leaderstat on Touched, then hides the part. Step 2 has the script.

Why do my coins only disappear for one player?

The coin was hidden by a LocalScript. Hide and pay out on the server, as CoinPickups does, so every player sees the same thing.

How do I make coins respawn?

Hide the coin with Transparency and CanTouch instead of destroying it, then turn them back with task.delay after a few seconds.

How do I make coins worth different amounts?

Give a coin a Number attribute named Value. The script pays that instead of COIN_VALUE.

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.