How would I make a coin system work with multiple coins?

I want to make a coin system where when you collect a coin it plays the sound locally. I used a RemoteEvent to do this with a single coin, this is the code I used.

Code

Local Script:

local coin = game.Workspace.Coin
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local coinCollection = ReplicatedStorage:WaitForChild("coinCollection")
local SoundService = game:GetService("SoundService")
local coinSound = Instance.new("Sound")
coinSound.Name = "CoinSound"
coinSound.SoundId = "rbxassetid://"..3302699870
coinSound.Parent = game.Workspace


local debounce = true
coin.Touched:Connect(function(player)
	if debounce == true then
		if player.Parent:FindFirstChild("Humanoid") ~= nil and player.Parent.Name == game.Players.LocalPlayer.Name then
			wait()
			debounce = false
			coinCollection:FireServer()
			coinSound:Play()
			wait(10)
			debounce = true
		end
	end
end)

Server Script:

local Players = game:GetService("Players")
local coin = script.Parent
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local coinCollection = ReplicatedStorage:WaitForChild("coinCollection")

function debounce(func)
	local isRunning = false
	return function(player)
		if not isRunning then
			isRunning = true

			func(player)

			isRunning = false
		end
	end
end


coinCollection.OnServerEvent:Connect(debounce(function(player)
	coin.Transparency = 1
	local player = player
	player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 1
	wait(10)
	coin.Transparency = 0
end))

Although this works fine with just 1 coin, I am puzzled on how I could get this to work with multiple coins.

You could simply use collectionservice and tag the coins like that

1 Like

First, you should put the script on the server. The .Touched connection is enough to handle it, and there is no need for a remote event.
Then you can clone the coin with a while loop and add a .Touched connection each time.

Edit: If you want a .Touched on the client for the sound to play locally, then have a .ChildAdded connection on the local script that makes a .Touched connection if the added child is a coin.

1 Like

Ok so would it be character.ChildAdded:Connect(function()?

If you clone the coin into workspace, then use

workspace.ChildAdded:Connect(function(child)
if child.Name == "Coin" then -- if the name is Coin
--do stuff
end
end)

Ok thanks for that suggestion!
I have never used CollectionService before so I am having some issues. I have this code so far:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local coinCollection = ReplicatedStorage:WaitForChild("coinCollection")
local SoundService = game:GetService("SoundService")
local coinSound = Instance.new("Sound")
coinSound.Name = "CoinSound"
coinSound.SoundId = "rbxassetid://"..3302699870
coinSound.Parent = game.Workspace



local CollectionService = game:GetService("CollectionService")

local taggedCoins = CollectionService:GetTagged("Coin")

local debounce = true
for _, taggedCoins in pairs(taggedCoins) do
	taggedCoins.Touched:Connect(function(hit)
		if debounce == true then
			if hit.Parent:FindFirstChild("Humanoid") ~= nil and hit.Parent.Name == game.Players.LocalPlayer.Name then
				wait()
				debounce = false
				coinSound:Play()
				coinCollection:FireServer()
				wait(10)
				debounce = true
			end
		end
	end)
end

But whenever I run over 1 coin, the rest also collect. I’m fairly certain this issue is coming from the FireServer line but I’m not 100% sure if it is and how I would fix it.

Did you add the tag to collect the coin? Also, you don’t really need fireserver() for this particular thing. You could simply put this in one function and inside that function you add the add for the coin.

function giveCoin(coin)
-- code for giving the player the coin every time they touch it
CollectionService:AddTag(coin, 'Coin')
end

I used the Tag Editor plugin to add the tag to the coins. I used a LocalScript for the code shown above, so would you recommend switching to a server script then fire the client where it will play a sound locally?

No you don’t need to use this on the server. Since all you want to do is play the sound locally, this can be in a local script or module script in replicatedstorage or wherever the client the access it.

All you’d do is add the tag and every time the player touches it, it plays the sound.

function coinSound(coin)
-- touched function
CollectionService:AddTag(coin, 'Coin')
end

CollectionService:GetInstanceAddedSignal('Coin'):Connect(coinSound)
CollectionService:GetInstanceRemovedSignal('Coin'):Connect(coinSound)

for _, inst in pairs(CollectionService:GetTagged('Coin')) do
coinSound(inst)
end

Edit: Going to assume you are handling the coin spawning and despawning, if not let me know.

I was handling the coin spawning and respawning on the server script which would have been fired before, that is also where I would change the players leaderstats.

Oh so let me clarify, all you want to do is just play a sound and that’s it? Or play a sound and change leaderstats? If you’re going to try and change leaderstats then obviously do this on the server. But since you said you just wanted to play a sound I assumed you just wanted this local

Basically what I want to do is a sound played locally, leaderstats changed and also the changes to the coin’s transparency. Im fairly certain you cant play a sound locally from a server script so would a fireclient have to be used when the coin is collected to then play a sound from a local script?