Creating a Coin Collection System

Creating a Coin Collection System

A tutorial by @LoveTheBears101


Hello friends. Over the years (or months, I’m not really sure how long I’ve been on the Dev Forum) I have seen a bunch of posts asking how to create coin collection systems. So here, I’m going to make a tutorial on making a coin collection system. This will include:

  • Randomly spawning coins
  • A leaderstat value in the leaderboard that counts the number of coins the player collected

In this tutorial, we are going to go over:

  • .Touched event
  • leaderstats
  • Random numbers

Let’s get started!


Step 1: Creating the coin
First, we need to create the coin. You can make the coin however you would like, but I’m going to make mine New Yeller (RGB: 255, 255, 0) with the material Metal. I also added a Surface Gui with a text label on it, if you don’t know what that is you can find Dev Hub articles about them here: Surface Guis and Text Label.


If you would like to use my coin to follow along, you can get it here: https://www.roblox.com/library/4989617656/Coin


Step 2: Finishing the coin
Now that we have created the coin, make sure the coin is Anchored, named Coin, and has CanCollide set to false.
image
Then, put it inside Server Storage.


Step 3: Setting up the leaderstats
Now that we have our coin, let’s create the leaderstats. Let’s start by creating a script inside of the workspace.
When a player has a folder named leaderstats inside of it, all the values inside of the folder is put into the leaderboard. So we need to make it so whenever a player spawns, it creates a folder named leaderstats inside of them and creates an IntValue named “Coins” inside of the folder.
We will do this by putting this inside the script:

local players = game:GetService("Players")

function playerSpawned(player)
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	
	local coins = Instance.new("IntValue", leaderstats)
	coins.Name = "Coins"
	coins.Value = 0
end

players.PlayerAdded:Connect(playerSpawned)

The function playerSpawned runs every time a player is added because we connected it to the PlayerAdded event. It creates a folder named ‘leaderstats’ inside the player and an Int Value named ‘Coins’ inside of the folder. Once you add this script, hit Play. You should see something like this (but with your username, of course):
image


Step 4: Setting up the coins
Now, we need it so when the player hits the coin, it adds one to their Coins or if you want to, you can make it add more than one for every coin so players get rich faster. We do this by creating a script inside the coin that says this:

local player = game:GetService("Players")
local coin = script.Parent -- Path to coin

local used = false

function giveCoin(part)
	if part.Parent:FindFirstChild("Humanoid") == nil or used == true then
		return
	end
	used = true
	local player = player:GetPlayerFromCharacter(part.Parent)
	player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 1
	
	coin:Destroy()
end

coin.Touched:Connect(giveCoin)

The function giveCoin runs every time the part is touched because we connected it to the Touched
The if...then loop checks to make sure the part that touched it is part of a character, and the used variable is whether the coin already has been used yet. After the function runs, it destroys the coin (and the script because the script is inside the coin).

Common Mistake: One of the most common mistakes with IntValues and String Values is people forget to do object.Value to change the value. This is bad because instead of changing the value of the object, it will try to change the object, which will cause an error.


Which script is correct if the script is inside of an Int Value?
a) script.Parent.Value = 123
b) script.Parent = 123
The correct answer is: (a)


Step 5: Spawning the coins
Now, we need the coins to spawn at random positions. Put this script in the workspace:

local coin = game.ServerStorage.Coin -- Path to coin

while true do
	local clone = coin:Clone()
	clone.Parent = game.Workspace
	clone.Position = Vector3.new(math.random(-226, 234), 2.834, math.random(-230, 231))
	wait(math.random(1, 5))
end

The while true do loop repeats forever. The script clones the coin inside of Server Storage, puts it in the workspace, and puts it in a random position. You may need the adjust the math.randoms according to your baseplate’s size. The y position is not random because we want to make sure the player can get to it always.

Common Mistake: while true do creates an infinite loop. However, if you don’t put a wait() in the infinite loop, it will cause an error because it will run the loop infinity with no cool down.


Now, Run your program! It should randomly spawn coins that increase the Coins leaderstat value when you touch them!

You can get the entire file here: CoinCollector.rbxl (100 TB jk it’s only 21.4 KB)


Bonus Lesson: Using Tween Service to make your coins spin!
If you want your coins to spin around in an infinite circle, you can use Tween Service.

But what does Tween Service do?

Great question. Tween service creates tweens that:

So we need to use TweenService:Create() to create a tween. Put this script inside of the coin (Which is inside of Server Storage):

local TweenService = game:GetService("TweenService")
local coin = script.Parent

local goal = {}
goal.Orientation = Vector3.new(0,360,0)

local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 2, false, 0)

local tween = TweenService:Create(coin, tweenInfo, goal)

while true do
	tween:Play()
	tween.Completed:Wait()
end
Note

Tweening parts to make them rotate is difficult. I would like to thank @jordanetoile1 for help with the rotating script from this post: Link to Devforum question about tweening.

The script uses tween service to make the coin spin. I’m not an expert on tweening parts, so if you want more info on how to do this, check out the def hub article above.

It should look like this when spinning:


Congrats! You finished this tutorial!

Or maybe you just skipped to the end and didn’t read anything lol.

The completed finished version can be found here:
CoinCollectorCompleted.rbxl (21.6 KB)

Please rate this tutorial on a scale of 1 (terrible) to 10 (AWESOME!)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

0 voters

If you have any questions/comments/errors, just say so in the replies!
Have a nice day.

If enough people like this, I may make a second tutorial.

95 Likes

Hey, nice tutorial! Hopefully, new developers willing to have a coin system in their game know the basics here!

AFAIK, I haven’t seen any coin system tutorials in this category.

7 Likes

I really like this tutorial, it’s clear, and descriptive. It shows you the right steps, and it’s simple, and the common mistake parts of the tutorial are an incredible touch!

If I had to point out one thing, it’d be about using TweenService to make the part spin. Why not just insert a BodyPosition in the coin, and a BodyAngularVelocity to make it spin?

2 Likes

That could work. I’m not an expert (or anywhere near an expert) at Roblox’s physics, so I will have to try that out.

2 Likes

Great tutorial. One thing though - the used variable that you are using will be used by all the clients. Meaning if Player1 sets used to true, it will be the same for Player2.

You can have a table with all the players in it and store a used value inside of it to prevent it being used by all the clients.

(I’m only assuming that you’re using the used variable for some sort of debounce - which can be countered by using a tick using the same method I provided above)

2 Likes

Yes, I am using used for denounce. I use it so if 2 player hits the coin at the same time, it only gives itself to one player. I purposely made it so used is the same for everyone. However, you are correct, if you put it in a table it’d let multiple player take it, the only problem is it’s destroyed after usage.

2 Likes

I see. Even then, you’re able to create a table with all the coins in it and you can have data attached to each one showing if it’s being used

1 Like

Love the tutorial! You explained things fairly thoroughly; it is sure to be helpful for beginner scripters like me and other people.

1 Like

Note: Thank you all for reading my tutorial!

3 Likes

You misspelled .Touched at the beginning by the way

1 Like

Thank you for pointing that out! I fixed it.

1 Like

Maybe a strange request, but is it possible to change the coin script to just add 1 every 5 seconds for example?

Nice, but I would recommend using a Connection instead of an infinite debounce.

Wow, that’s amazing, that litearlly helped me so much.
i have a question
Do you know how to make the coins spawn in specific places instead of random?

Hi! I have a question, how can I make it that the coins appear in specific places, and after the player collects them and rejoins, the coins don’t respawn? (so they can’t have unlimited coins by getting them and rejoining, because i’m using a datastore to save them) i searched for an answer everywhere but i can’t find anything i guess

1 Like

Thats simple! .Put the coin in where the position to spawn and delete every time then add this script inside it


local Coin = script.Parent 
Coin.Touched:Connect(function(player)
player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 1

Coin:Destroy()

wait(5) 

local coinclone = Coin:Clone()
coinclone.Parent = workspace
coinclone.CFrame = Coin.CFrame

end)

3 Likes

@kaixiuuu I can show you how to make a dropper/generator if you want!

1 Like

I think I have something that will help you even better!..A Dropper/Generator

Dropper Making

So first let’s make our dropper, a part for this instance, make it kind of blocky, put it in the sky not in the ground, anchor it, can collide is false, now rename it to Dropper, set transparency to 0.7, there our dropper is done

Coin Making

You already have your coin and that’s good, then this is important, put your coin IN the dropper. Not like set the coin as a child to the dropper, like put it in the dropper, the coin has to be smaller than the dropper or it wont work, so after you put your coin IN the dropper, (dropper and coin’s parent should be Workspace) ok now lets script,

Script Making

Make a script in ServerScriptService, delete the “print(“Hello World!”) and type the following

local Dropper = workspace.Dropper --we get our dropper

local Coin = workspace.Coin --we get our coin

while true do --we make a loop

local CoinClone = Coin:Clone() --we clone our coin

CoinClone.Parent = Dropper --We set the coin clone's parent to dropper

CoinClone.CFrame = Dropper.CFrame --We set the coin clone's position to the dropper's position

wait(2) --Wait so it wont crash

end)
1 Like

How do I limit the max cloned coin number to 10 on the server and pause the cloning when the cloned coin on the server is >=10 and whenever the cloned coin on the server is less than 10 it will start cloning the coin again until it hit the maxed cloned number 10 again?

local function SpawnCoins()
        -- Do the clone
        -- Touch event
        -- when the player touches the coin destroy it then call the function again
       SpawnCoins()
end

for i = 1, 10 do
     SpawnCoins()
end
1 Like