Coin Collecting Issue

I am using the Collection Service, datastore2, and gamepasses for the coins just to be clear

The coin is in the workspace, and I used the tag plugin to tag it. There is no script inside it.

In the Starter player scripts, I have the following script:

local collectS = game:GetService("CollectionService")
local coin1tagged = collectS:GetTagged("Coin1")
local playerService = game:GetService("Players")

for _, coin1tagged in pairs(coin1tagged) do 
	
	
	
coin1tagged.Touched:Connect(function(hit)
		local debounce = true
		if hit.Parent:FindFirstChild("Humanoid") ~= nil then
			if debounce == true then
				debounce = false
				coin1tagged.Transparency = 1
				local player = playerService:GetPlayerFromCharacter(hit.Parent)
				if player ~= nil then
					game.ReplicatedStorage.CoinRemoteEvents.RemoteEvent:FireServer(player, 1)
				coin1tagged.Parent = game.ReplicatedStorage.Storage
		
				wait(60)
				
				debounce = true
				end
			end
		end
	end)

end

In the ServerScriptService, I have the following script:

local coinsTimers = {} -- our new array that will track coin pick up times!
local regenTime = 10 -- set this to your regeneration timer in seconds
game:GetService("ReplicatedStorage").CoinRemoteEvents.RemoteEvent.OnServerEvent:Connect(function(player, coin) -- your awardCoin remote event (or whatever you refer to it as ;p).
    local awardCoin = false -- if this is not met as true by the end of the checks, coin is not awarded.
    if coinsTimers[player.Name] ~= nil  then -- has the player recieved a coin? If not they won't have a value in the array yet.
        local coinFound = false -- if this is not found in the array and set to true, the coin has not been picked up yet and thus will be added with a timer and awardCoin will be set to true.
        local i = 0 -- track how many times the loop has ran in case we need to remove the old tick() value if the coin is eligible to be picked up.
        for savedCoin, lastTime in pairs(coinsTimers[player.Name]) do -- loop through all the current saved data in the array. Unfortunately, we cannot directly refer to the coin since we also have to save the tick as well.
            i = i + 1
            if coin == savedCoin then -- if this is the coin we are looking for..
                coinFound = true -- we found the coin!
                if tick() - lastTime > regenTime then -- check if it has been long enough!
                    awardCoin = true -- this coin should be awarded!
                    table.remove(coinsTimers, i) -- delete the old time assigned to the coin.
                    table.insert(coinsTimers, {coin, tick()}) -- add the new time assigned to the coin.
                end
                break
            end
        end
        if not coinFound then -- if coin wasn't found in the saves, award the coin!
            table.insert(coinsTimers[player.Name], {coin, tick()})
            awardCoin = true
        end
    else -- the player does not have data yet, lets add it!
        awardCoin = true
        coinsTimers[player.Name] = {}
        table.insert(coinsTimers[player.Name], {coin, tick()})
    end
    if awardCoin then -- the checks proved the coin should be awarded, lets give them a coin!
-------------------------------------------------------------
--This is datastore2 and gamepasses
				local MarketplaceService = game:GetService("MarketplaceService")
				local playerService = game:GetService("Players")
				local DataStore2 = require(game:GetService("ServerScriptService"):WaitForChild"MainModule")
				local defaultAmount = 1
	
				local twotimesID = 7158220 --2x
				local threetimesID = 7172665 --3x
				local fivetimesID  = 7172700 --5x
		
		
		
		

	
					local leaderstats = player.leaderstats
					local coins = leaderstats.Coins
					local xp = leaderstats.XP
					local coinDataStore = DataStore2("Coins",player)
					local expDataStore = DataStore2("XP",player)
					
					local function coinUp(UpValue)
						coins.Value = coinDataStore:Get(UpValue)
					end
				
					local function expUp(UpExpValue) -- This is for a level up system
						xp.Value = expDataStore:Get(UpExpValue)
					end
					
					if MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID)== nil then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 2x
						coinDataStore:Increment(2 * defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID)== nil then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 3x
						coinDataStore:Increment(3* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 5x
						coinDataStore:Increment(5* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID)== nil then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 2x and 3x
						coinDataStore:Increment(2*3* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID)== nil and  MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 2x and 5x
						coinDataStore:Increment(2*5* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 3x and 5x
						coinDataStore:Increment(3*5* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns all coin gamepasses
						coinDataStore:Increment(2*3*5* defaultAmount,0)
					else
						coinDataStore:OnUpdate(coinUp)	--owns none----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- HE IS POOR XD
						coinDataStore:Increment(defaultAmount,0)
					end

			



    end
end)

Please let me know if there are any mistakes.I did test this and it doesn’t work, so let me know what I did wrong. Thanks!

Before I read all of this, were there any errors in the output? Did anything happen, or just nothing at all?

Nothing at all happened in the output, could you maybe show me an example of the local script in the StarterPlayerScripts.

Does the coin go transparent once you touch it? Or nothing happens at all?

Edit: In your local script remote event you need to send the coin object as the parameter (not 1).

game.ReplicatedStorage.CoinRemoteEvents.RemoteEvent:FireServer(player, coin1tagged)

I thought that whenever you reparent an object from the workspace to replicated storage it would just disappear in the workspace. Is that the case or not. If it isn’t, then I should add the more to the script to make it disappear. Also if my script in starterPlayerScripts is bad, could you show me an example of what it should look like. Thanks!

It is the case, and if you do it on the client it will only disappear for that player. The server would still recognize it as in the workspace.

I have never used the tag method you used, so I am not sure exactly how that works. Other than that, and the changes I mentioned before, it should work just fine.

Edit: You do need to make sure you check that the coin isn’t transparent already, otherwise the player is going to be able to pick it up over and over again even though they can’t see it (since we added a cooldown on the server, it shouldn’t actually give them the coin, but it will still send unnecessary remote events). If you move it to repStorage instead of the transparency, then you don’t need to worry about checking if it’s already been picked up (locally), since they can’t trigger the Touched event when it isn’t in the workspace.

Its not working. I think it has something to do with the local script in the starterPlayerScripts, because it seems like the remote event is never fired. Could you give me an example of what the code should look like?

I think the issue is your method of using tags. You should instead create an array and add every coin in the workspace to it, then loop through that for your local script (instead of the “tagged” coin1).

Could I just create a folder where all the coins are then say GetChildren, or should I do what you said.
Also if I put in the following code in StarterPlayerScripts:

local coin = game.Workspace.Coins.Coin1--my coin in a folder, which is "Coins"

It would say in the output that its not a member in the workspace
This is my updated version of the script.

local allcoins = game.Workspace.Coins:GetChildren()
local playerService = game:GetService("Players")

	
for _,v in pairs(allcoins) do	
	
v.Touched:Connect(function(hit)
		local debounce = true
		if hit.Parent:FindFirstChild("Humanoid") ~= nil then
			if debounce == true then
				debounce = false
				local player = playerService:GetPlayerFromCharacter(hit.Parent)
				if player ~= nil then
					game.ReplicatedStorage.CoinRemoteEvents.RemoteEvent:FireServer(player, 1)
				v.Parent = game.ReplicatedStorage.Storage
		
				wait(60)
				
				debounce = true
				end
			end
		end
	end)
end

Also am I supposed to get rid of the wait in this script or not? Sorry if you already answered this.
If I am still not getting it would it be okay if we could do a team create so you can show me?

Yes, either way will work!

Do you have a coin named “Coin1”? Did you name them by number? You don’t need to if you haven’t, but if they aren’t that is why you are getting that error in the output.

Your debounce should not be created inside the .Touched event. This would always pass true. You should move it to the line above; right after the for _, v in ipairs is begun (you should change to ipairs, not pairs. Use ipairs when you are using a table where the index is ascending integers). It needs to be within the loop to ensure that each coin has its own debounce Boolean.

You still need to change your remote event to send the coin you touched as the parameter, not 1. Also, the player is sent to the server by default (in the remote event), so if you try to send the player, then it’s going to receive three parameters (player, player, coin). Update your remote event to this;

game.ReplicatedStorage.CoinRemoteEvents.RemoteEvent:FireServer(v)

You need to reparent the coin to the coins folder once the 60 seconds is up, otherwise it will never come back.


If you make all of these changes and still cannot get it to work, I am willing to join your TC to help you sort it out.

So I just disabled streaming enabled and it would allow the player to collect it, when originally it didn’t. So what does streaming enabled even do?

With streaming enabled set to true, you allow the player to join the game before it is done loading. This means that parts and other instances may not yet be replicated to the client when the game starts. This is for games where the Creator is not concerned if the players have loaded everything (or certain things if you manually force the player to load specified instances first) so that players can join faster. It also allows instances to be destroyed (locally) that are no longer in range of the player (not rendered).


Taken from the dev hub.

Furthermore, since your code relies on tags, you should note that the tags can be lost, as explained in the link posted above (image posted below).

I am doing what your saying, but it isn’t working. Since I come from a big family, and have a lot of stuff planned cause its the holiday, I am afraid I you cant join me in studio at the same time. However, maybe could you just create a game and allow me to have access to it to rap this up. I am trying to get this update by Christmas.
Thanks!

I am busy too between family, friends, work, and developing a game. I don’t have time to do that for you.

If you post any errors, and relevant code then I can help you.

Alright, here is the new revamped code in the starter player scripts

local allcoins = game.Workspace.Coins:GetChildren()
local playerS = game:GetService("Players")

	
for _,v in ipairs (allcoins) do	
	local debounce = true
	v.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") ~= nil then
			if debounce == true then
				debounce = false
				if playerS:GetPlayerFromCharacter(hit.Parent) ~= nil then
	
					game.ReplicatedStorage.CoinRemoteEvents.RemoteEvent:FireServer(v)
					v.Parent = game.ReplicatedStorage.Storage
					wait(4)
					v.Parent = game.Workspace.Coins
					debounce = true
				end
			end
		end
	end)
end

Does the coin disappear when you touch it? This looks pretty good actually! I just need to see the server script now for the remote event.

What does it do? What doesn’t it do? Any errors in the output??

When a player touches it, it disappers on both clients. It also gives them both the coin amount. For example, lets say bob got the coin. Both bob and every one else on the server got the coin. There is no errors in the output. Here is the script in ServerScriptService:

local regenTime = 4 -- set this to your regeneration timer in seconds
game:GetService("ReplicatedStorage").CoinRemoteEvents.RemoteEvent.OnServerEvent:Connect(function(player, coin) -- your awardCoin remote event (or whatever you refer to it as ;p).
    local awardCoin = false -- if this is not met as true by the end of the checks, coin is not awarded.
    if coinsTimers[player.Name] ~= nil  then -- has the player recieved a coin? If not they won't have a value in the array yet.
        local coinFound = false -- if this is not found in the array and set to true, the coin has not been picked up yet and thus will be added with a timer and awardCoin will be set to true.
        local i = 0 -- track how many times the loop has ran in case we need to remove the old tick() value if the coin is eligible to be picked up.
        for savedCoin, lastTime in pairs(coinsTimers[player.Name]) do -- loop through all the current saved data in the array. Unfortunately, we cannot directly refer to the coin since we also have to save the tick as well.
            i = i + 1
            if coin == savedCoin then -- if this is the coin we are looking for..
                coinFound = true -- we found the coin!
                if tick() - lastTime > regenTime then -- check if it has been long enough!
                    awardCoin = true -- this coin should be awarded!
                    table.remove(coinsTimers, i) -- delete the old time assigned to the coin.
                    table.insert(coinsTimers, {coin, tick()}) -- add the new time assigned to the coin.
                end
                break
            end
        end
        if not coinFound then -- if coin wasn't found in the saves, award the coin!
            table.insert(coinsTimers[player.Name], {coin, tick()})
            awardCoin = true
        end
    else -- the player does not have data yet, lets add it!
        awardCoin = true
        coinsTimers[player.Name] = {}
        table.insert(coinsTimers[player.Name], {coin, tick()})
    end
    if awardCoin then -- the checks proved the coin should be awarded, lets give them a coin!
-------------------------------------------------------------
--This is datastore2 and gamepasses
				local MarketplaceService = game:GetService("MarketplaceService")
				local playerService = game:GetService("Players")
				local DataStore2 = require(game:GetService("ServerScriptService"):WaitForChild"MainModule")
				local defaultAmount = 1
	
				local twotimesID = 7158220 --2x
				local threetimesID = 7172665 --3x
				local fivetimesID  = 7172700 --5x
		
		
		
		

	
					local leaderstats = player.leaderstats
					local coins = leaderstats.Coins
					local xp = leaderstats.XP
					local coinDataStore = DataStore2("Coins",player)
					local expDataStore = DataStore2("XP",player)
					
					local function coinUp(UpValue)
						coins.Value = coinDataStore:Get(UpValue)
					end
				
					local function expUp(UpExpValue) -- This is for a level up system
						xp.Value = expDataStore:Get(UpExpValue)
					end
					
					if MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID)== nil then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 2x
						coinDataStore:Increment(2 * defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID)== nil then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 3x
						coinDataStore:Increment(3* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 5x
						coinDataStore:Increment(5* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID)== nil then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 2x and 3x
						coinDataStore:Increment(2*3* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID)== nil and  MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 2x and 5x
						coinDataStore:Increment(2*5* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)== nil and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns ONLY 3x and 5x
						coinDataStore:Increment(3*5* defaultAmount,0)
					elseif MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),twotimesID)and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),threetimesID) and MarketplaceService:UserOwnsGamePassAsync(playerService:GetUserIdFromNameAsync(player.Name),fivetimesID) then
						coinDataStore:OnUpdate(coinUp)	--owns all coin gamepasses
						coinDataStore:Increment(2*3*5* defaultAmount,0)
					else
						coinDataStore:OnUpdate(coinUp)	--owns none---------------------------------
						coinDataStore:Increment(defaultAmount,0)
					end

			



    end
end)**

The problem is that you are checking if the humanoid and the player exist, but not checking if the player themself matches the humanoid/player.

local allcoins = game.Workspace.Coins:GetChildren()
local playerS = game:GetService("Players")

for _,v in ipairs (allcoins) do	
	local debounce = true
	v.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
                local plr = players:GetPlayerFromCharacter(hit.Parent)
	        	if debounce and plr and plr == playerS.LocalPlayer then
					game.ReplicatedStorage.CoinRemoteEvents.RemoteEvent:FireServer(v)
					v.Parent = game.ReplicatedStorage.Storage
					wait(4)
					v.Parent = game.Workspace.Coins
					debounce = true
				end
			end
		end
	end)
end

Finally, It WORKS!! Thank you so much for helping me with this. Sorry this took so much time though. Thanks Again!

1 Like