Make an item only be collected client side

Hi, I was wondering if anyone can help me on this.
I am trying to create a game in which there are two collectible items, one of which is a coin.
Upon touching these coins, they get added to a count and become transparent, as well as having their cantouch disabled. This is meant to be a client side script, which I have so far been able to do.

The only problem with this is that upon one player touching the coin, it becomes uncollectable for all other players, and I intend for this game to be a multiplayer game.
I have been able to set up a remote event and upon touching the coin, it fires only for the client. Supposedly this is meant to make the collection client side, but the remotefunction does not work.
I assume that this is because I have either placed the localscript in playerscripts or that the localscript does not connect to the remote event properly. This makes it so that the coin is collected more than once, which is a problem.

I haven’t really found much solutions on other pages of this site, and I don’t really know how to use remote events besides the developer page for them.

The script on the coin

local count = workspace.Coins.coincount.Value
local lplayer = game.Players.LocalPlayer

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = Instance.new("RemoteEvent")
remoteEvent.Parent = game.ReplicatedStorage
remoteEvent.Name = "coin3"

coin.Touched:Connect(function(collected)
	local possiblehumanoid = collected.Parent:FindFirstChildWhichIsA("Humanoid")
	if possiblehumanoid then
		if possiblehumanoid.Parent == lplayer then
			if script.Parent.collected.Value == false then
				local player = collected.Parent
				if player then
					remoteEvent:FireClient(player)
				end
				script.Parent.collected.Value = true
			end
			if script.Parent.collected.Value == true then
				script.Parent.CanTouch = false
			end
		end
	end
end)

The local script

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = Players.LocalPlayer

local redcoin1 = ReplicatedStorage:WaitForChild("coin1")
local redcoin2 = ReplicatedStorage:WaitForChild("coin2")
local redcoin3 = ReplicatedStorage:WaitForChild("coin3")

redcoin3.OnClientEvent:Connect(function(coin3get)
	print("this")
	workspace.Coins.coin3.Transparency = 0.5
	workspace.Coins.coin3.CanTouch = false
end)
3 Likes

Isnt the script in the coin a server script tho? How can you say local player in a server script?

What you can do is have the coin and touched event to give the player a point on the server but once they touch the coin instead of deleting the coin have the coin add that player onto a table and anyone on that table the coin will not give a point to. Then have the coin’s sever script fire a remote event to the client to delete the coin on the client. So now you have a coin that the client sees to disappear when they touch it, but on the server it’s not actually disappearing but just disabling its effect to whoever touches it. Also you can make it check if everyone in the server has touched it already and if they have then delete it on the server just to save memory for the server.

2 Likes

It looks like it is working, however when I try it with more than one player, the first player is added to the table, but later players who attempt to touch the coin are not added on

local playertable = {}
local inTable = false

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = game.ReplicatedStorage.coin3

coin.Touched:Connect(function(collected)
	local possiblehumanoid = collected.Parent:FindFirstChildWhichIsA("Humanoid")
	local player = Players:GetPlayerFromCharacter(collected.Parent)
	if possiblehumanoid then
		for _,difplayer in next,playertable do
			if difplayer == player then
				inTable = true
				if inTable then
					remoteEvent:FireClient(player)
				end
			end
		end
		
		if not inTable then
			table.insert(playertable,player)
			print(player.Name .. "Intable")
		end
	end			
end)

The reason is because you’re using inTable as a bool for the entire server. So once u set inTable to true it sets it to true for everyone. To check if someone’s in a table use

if table.find(playertable,player) then
     table.insert(playertable,player)
end
2 Likes

Thank you, this works. I only have one issue left and it’s about how to set up a debounce.
When I touch the part, it gives about 5 coins instead of one as it takes a while for the remote event to register and the collisions to disable. I have a separate script set up for the collection system. Would I put it on that script, the script on the coin or on the local script?

Collection script:


local isTouched = false


for _,v in pairs(folder:GetChildren()) do
	if v:IsA("BasePart") then
		v.Touched:Connect(function(touched)
			local possiblehumanoid = touched.Parent:FindFirstChildWhichIsA('Humanoid')
			if possiblehumanoid then
				local player = game.Players:GetPlayerFromCharacter(touched.Parent)
				
				local leaderstats = player.leaderstats
				local coinstat = leaderstats and leaderstats:FindFirstChild("coins")

				
				if coinstat then
					coinstat.Value = coinstat.Value + 1
				end				
				coinstat.Changed:Connect(function(test)
					if coinstat.Value == 8 then
						if not isTouched then
						local cuboidstat = leaderstats and leaderstats:FindFirstChild("Cuboids")
							if cuboidstat then
								print("cuboid")
								cuboidstat.Value = cuboidstat.Value + 1
								isTouched = true
							end
						end
					end
				end)

			end
			
		end)
		
	end
	
end

This will make it so that once the player touches it they’re added to the table. And it’ll run if they’re not in the table

local playertable = {}
if possiblehumanoid and not table.find(playertable,player)then
     table.insert(playertable,player)
end

Is there any way that I can edit the script so that it adds one coin to the value without adding more, like adding wait() or limiting how much a value can change in a set amount of time?

Nevermind, I just needed to add another debounce to the value change on collection