Coins sometimes dissapear after seconds

Hello, so i made a coin system for my platformer. Basically, when the Server detects a coin being touched, it checks if there’s humanoid in it, and if there is, then it gets the player from the humanoid’s parent (character) and then it adds to the value of the leaderboard. On the Client, there’s all the fancy little effects like the Coin dissapearing and playing an animation and stuff. I made the exact same thing for my Crystal system (another collectible). The thing is, for both of them, some times when i test the game and go to collect coins or a crystal, they take a while to dissapear, and there is no effect or sound at all when they dissapear. Here’s a video :

And the code :

Client

--//Services//--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--//Variables//--
local Player = Players.LocalPlayer
local LeaderStats = Player:WaitForChild("leaderstats")
local CoinVal = LeaderStats.Coins
local PlayerGui = Player.PlayerGui
local MainGui = PlayerGui:WaitForChild("MainGui")
local Coins = MainGui.Coins
local CoinsFolder = workspace.Coins
local CoinDisplay = Coins.CoinDisplay
--//Function//--
for __, Coin in pairs(CoinsFolder:GetChildren()) do
	local Sparkles = Coin:WaitForChild("Sparkles")
	local Light = Coin:WaitForChild("PointLight")
	local Collect = Coin:WaitForChild("Collect")
	local function onTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			Coin.CanTouch = false
			Collect:Play()
			Light:Destroy()
			Sparkles.Enabled = true
			Coin.Transparency = 1
			Collect:Play()
			Sparkles:Emit()
		end
	end
	Coin.Touched:Connect(onTouched)
end
-----------------------------------------------------
while true do
	CoinDisplay.Text = "x"..CoinVal.Value
	task.wait()
end
-----------------------------------------------------
--//Services//--
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--//Variables//--
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Root = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")
local Head = Character:WaitForChild("Head")
local LeaderStats = Player:WaitForChild("leaderstats")
local CrystalVal = LeaderStats.Crystals
local PlayerGui = Player.PlayerGui
local MainGui = PlayerGui:WaitForChild("MainGui")
local Crystals = MainGui.Crystals
local CrystalDisplay = Crystals.CrystalDisplay
local CrystalsFolder = workspace.Crystals
local TweenInform = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
--//Function//--
for __, Crystal in pairs(CrystalsFolder:GetChildren()) do
	local GreenSparkles = Crystal.GreenSparkles
	local GreenGlow = Crystal.GreenGlow
	local Light = Crystal.PointLight
	local Glow = Crystal.Glow
	local Collect = Crystal.Collect
	local CSnd = Crystal.CSnd
	local function onTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			Glow:Stop()
			Collect:Play()
			CSnd:Play()
			Crystal.CanTouch = false
			Crystal.Transparency = 1
			GreenSparkles:Destroy()
			GreenGlow:Destroy()
			Light:Destroy()
			local GreenExplosion = Instance.new("Part", Root)
			GreenExplosion.Size = Vector3.new(.5,.5,.5)
			GreenExplosion.BrickColor = BrickColor.new(0, 255, 0)
			GreenExplosion.Material = Enum.Material.Neon
			GreenExplosion.Shape = Enum.PartType.Ball
			GreenExplosion.Position = Root.Position
			GreenExplosion.Transparency = 0
			GreenExplosion.CanCollide = false
			local Weld = Instance.new("WeldConstraint", GreenExplosion)
			Weld.Part0 = GreenExplosion
			Weld.Part1 = Root
			local TweenInform = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
			local TweenGE = TweenService:Create(GreenExplosion, TweenInform, {Size = Vector3.new(6, 6, 6), Transparency = 1})
			TweenGE:Play()
			task.wait(.5)
			GreenExplosion:Destroy()
		end
	end
	Crystal.Touched:Connect(onTouched)
end
-----------------------------------------------------
while true do
	CrystalDisplay.Text = "x"..CrystalVal.Value
	task.wait()
end
-----------------------------------------------------

Server

--//Variables//--
local Players = game:GetService("Players")
--------------------------------------------
local CoinsFolder = workspace.Coins
local CoinTable = CoinsFolder:GetChildren()
local IBFolder = workspace.ItemBlocks
local IBTable = IBFolder:GetChildren()
local CrystalsFolder = workspace.Crystals
local CrystalTable = CrystalsFolder:GetChildren()
--//Function//--
local function onPlayerAdded(Player)
	local function onCharacterAdded()
		local Character = Player.Character or Player.CharacterAdded:Wait()
		local Humanoid = Character:WaitForChild("Humanoid")
		local Root = Character:WaitForChild("HumanoidRootPart")
		local LeaderStats = Instance.new("Folder")
		Humanoid.WalkSpeed = 26
		Humanoid.JumpPower = 50
		LeaderStats.Name = "leaderstats"
		---------------------------
		local Coins = Instance.new("IntValue")
		Coins.Name = "Coins"
		Coins.Value = 0
		Coins.Parent = LeaderStats
		---------------------------
		local Crystals = Instance.new("IntValue")
		Crystals.Name = "Crystals"
		Crystals.Value = 0
		Crystals.Parent = LeaderStats
		---------------------------
		LeaderStats.Parent = Player
	end
	Player.CharacterAdded:Connect(onCharacterAdded)
end
--------------------------------------------
for __, Coin in pairs(CoinTable) do
	local function onCoinTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			local Humanoid = Hit.Parent:FindFirstChild("Humanoid")
			---------------------------------------------------------
			local Player = Players:GetPlayerFromCharacter(Humanoid.Parent)
			---------------------------------------------------------
			if Player == nil then
				return
			end
			--------------------------------------------------------------------------------
			local LeaderStats = Player:WaitForChild("leaderstats")
			local CoinVal = LeaderStats:WaitForChild("Coins")
			CoinVal.Value = CoinVal.Value + 1
			task.wait(0.5)
			Coin:Destroy()
		end
	end
	Coin.Touched:Connect(onCoinTouched)
end
--------------------------------------------
for __, Block in pairs(IBTable) do
	if Block:IsA("Model") and Block.Name == "ItemBlock" then
		local Hitbox = Block.Hitbox
		local HitS = Hitbox.HitS
		local function onTouched(Hit)
			if Hit and Hit.Parent:FindFirstChild("Humanoid") then
				---------------------------------------------------------
				local Player = Players:GetPlayerFromCharacter(Hit.Parent)
				---------------------------------------------------------
				if Player == nil then
					return
				end
				--------------------------------------------------------------------------------
				local LeaderStats = Player:WaitForChild("leaderstats")
				local CoinVal = LeaderStats:WaitForChild("Coins")
				CoinVal.Value = CoinVal.Value + 5
			end
		end
		Hitbox.Touched:Once(onTouched)
	end
end
--------------------------------------------
for __, Crystal in pairs(CrystalTable) do
	local function onCrystalTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			local Humanoid = Hit.Parent:FindFirstChild("Humanoid")
			---------------------------------------------------------
			local Player = Players:GetPlayerFromCharacter(Humanoid.Parent)
			---------------------------------------------------------
			if Player == nil then
				return
			end
			--------------------------------------------------------------------------------
			local LeaderStats = Player:WaitForChild("leaderstats")
			local CrystalVal = LeaderStats:WaitForChild("Crystals")
			CrystalVal.Value = CrystalVal.Value + 1
			task.wait(2.5)
			Crystal:Destroy()
		end
	end
	Crystal.Touched:Once(onCrystalTouched)
end
--------------------------------------------
Players.PlayerAdded:Connect(onPlayerAdded)

The server will always run later than the client. I suggest moving the .Touched scripts to the LocalScript, which then fires a RemoteEvent to the server to delete the coin.


Optional: From there you can also choose to :FireAllClients() to make the effect visible for everyone when some one picks up a coins.

Thanks, i managed to get it to work but now there’s so many Infinite Yield Possible in the output, let me show you the code :

Client

--//Services//--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--//Variables//--
local EventsFolder = ReplicatedStorage.Events
local CoinEvent = EventsFolder.CoinEvent
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local LeaderStats = Player:WaitForChild("leaderstats")
local CoinVal = LeaderStats.Coins
local PlayerGui = Player.PlayerGui
local MainGui = PlayerGui:WaitForChild("MainGui")
local Coins = MainGui.Coins
local CoinsFolder = workspace.Coins
local CoinDisplay = Coins.CoinDisplay
--//Function//--
for __, Coin in pairs(CoinsFolder:GetChildren()) do
	local function onTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			local PlayerHit = Players:GetPlayerFromCharacter(Hit.Parent)
			if PlayerHit == nil then
				return
			end
			CoinEvent:FireServer(CoinVal, Coin)
		end
	end
	Coin.Touched:Connect(onTouched)
end
-----------------------------------------------------
while true do
	CoinDisplay.Text = "x"..CoinVal.Value
	task.wait()
end
-----------------------------------------------------

Server

--//Services//--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
--//Variables//--
local EventsFolder = ReplicatedStorage.Events
local CoinsFolder = workspace.Coins
local CoinTable = CoinsFolder:GetChildren()
local IBFolder = workspace.ItemBlocks
local IBTable = IBFolder:GetChildren()
local CrystalsFolder = workspace.Crystals
local CrystalTable = CrystalsFolder:GetChildren()
--//Function//--
local function onPlayerAdded(Player)
	local function onCharacterAdded()
		local Character = Player.Character or Player.CharacterAdded:Wait()
		local Humanoid = Character:WaitForChild("Humanoid")
		local Root = Character:WaitForChild("HumanoidRootPart")
		local LeaderStats = Instance.new("Folder")
		Humanoid.WalkSpeed = 26
		Humanoid.JumpPower = 50
		LeaderStats.Name = "leaderstats"
		---------------------------
		local Coins = Instance.new("IntValue")
		Coins.Name = "Coins"
		Coins.Value = 0
		Coins.Parent = LeaderStats
		---------------------------
		local Crystals = Instance.new("IntValue")
		Crystals.Name = "Crystals"
		Crystals.Value = 0
		Crystals.Parent = LeaderStats
		---------------------------
		LeaderStats.Parent = Player
	end
	Player.CharacterAdded:Connect(onCharacterAdded)
end
--------------------------------------------
local function onCoinEvent(Player, CoinVal, Coin)
	local Sparkles = Coin:WaitForChild("Sparkles")
	local Light = Coin:WaitForChild("PointLight")
	local Collect = Coin:WaitForChild("Collect")
	--------------------------------------------
	Coin.CanTouch = false
	Collect:Play()
	Light:Destroy()
	Sparkles.Enabled = true
	Coin.Transparency = 1
	Collect:Play()
	Sparkles:Emit()
	CoinVal.Value = CoinVal.Value + 1
	task.wait(0.5)
	Coin:Destroy()
end
--------------------------------------------
local function onIBEvent(Player, CoinVal, Block, isBrown)
	local Surfaces = Block:WaitForChild("Surfaces")
	local Left = Surfaces:WaitForChild("Left")
	local Right = Surfaces:WaitForChild("Right")
	local Bottom = Surfaces:WaitForChild("Bottom")
	local Top = Surfaces:WaitForChild("Top")
	local Center = Block.Center
	local Hitbox = Block.Hitbox
	local HitS = Hitbox.HitS
	local Collect = Hitbox.Collect
	local Light = Center.SpotLight
	local Sparkles = Center.Sparkles
	--------------------------------------------
	isBrown = true
	Collect:Play()
	Hitbox.CanTouch = false
	Sparkles.Enabled = true
	Light:Destroy()
	HitS:Play()
	Collect:Play()
	Left:Destroy()
	Right:Destroy()
	Bottom.BrickColor = BrickColor.new("Dark orange")
	Top.BrickColor = BrickColor.new("Dark orange")
	Center.BrickColor = BrickColor.new("Dark orange")
	local BlockTInfo = TweenInfo.new(0.25, Enum.EasingStyle.Bounce, Enum.EasingDirection.In)
	local TweenUp = TweenService:Create(Center, BlockTInfo, {CFrame = Center.CFrame + Vector3.new(0, 1, 0)})
	local TweenDown = TweenService:Create(Center, BlockTInfo, {CFrame = Center.CFrame - Vector3.new(0, 0.5, 0)})
	TweenUp:Play()
	task.wait(0.4)
	Sparkles:Destroy()
	TweenDown:Play()
end
--------------------------------------------
local function onCrystalEvent(Player, CrystalVal, Crystal, Root)
	local GreenSparkles = Crystal:WaitForChild("GreenSparkles")
	local GreenGlow = Crystal.GreenGlow
	local Light = Crystal.PointLight
	local Glow = Crystal.Glow
	local Collect = Crystal.Collect
	local CSnd = Crystal.CSnd
	--------------------------------------------
	Glow:Stop()
	Collect:Play()
	CSnd:Play()
	Crystal.CanTouch = false
	Crystal.Transparency = 1
	GreenSparkles:Destroy()
	GreenGlow:Destroy()
	Light:Destroy()
	local GreenExplosion = Instance.new("Part", Root)
	GreenExplosion.Size = Vector3.new(.5,.5,.5)
	GreenExplosion.BrickColor = BrickColor.new(0, 255, 0)
	GreenExplosion.Material = Enum.Material.Neon
	GreenExplosion.Shape = Enum.PartType.Ball
	GreenExplosion.Position = Root.Position
	GreenExplosion.Transparency = 0
	GreenExplosion.CanCollide = false
	local Weld = Instance.new("WeldConstraint", GreenExplosion)
	Weld.Part0 = GreenExplosion
	Weld.Part1 = Root
	local CrystalTI = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
	local TweenGE = TweenService:Create(GreenExplosion, CrystalTI, {Size = Vector3.new(6, 6, 6), Transparency = 1})
	TweenGE:Play()
	task.wait(.5)
	GreenExplosion:Destroy()
end
--//Connections//--
Players.PlayerAdded:Connect(onPlayerAdded)
EventsFolder.CoinEvent.OnServerEvent:Connect(onCoinEvent)
EventsFolder.ItemBlockEvent.OnServerEvent:Connect(onIBEvent)
EventsFolder.CrystalEvent.OnServerEvent:Connect(onCrystalEvent)

Here’s a video :

And even then sometimes i just can’t collect the coins or crystals.

The error means there’s still no child called “PointLight” in Coin.

There is, but i don’t know why it’s saying it’s not there, probably because it destroys the light as soon as it’s touched? But even when i put a task.wait(0.01) before destroying it, it still tells me attempt to index nil with :Destroy().

Have you checked if there’s PointLight on the server? You may have, but im just trying to make sure.

Yes, it is indeed there.

The most probable reason I can think of is that you destroyed the Coin on the server immediately after touching it. If not, check the coin’s children on the server while moving the character to the Coin to touch it and see if anything happens to the children

Edit: I’ve just checked the script again and saw that you destroyed the Coin only after that waitforchild, so I guess it’s either another script is destroying the coin or you’re firing multiple CoinEvent events on the same coin

Actually, i just defined the children of the Coin on the client, and then i sent them over to the Server so now no more warnings. But for some reason the sparkles appear a LOT brighter?

Client

--//Services//--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--//Variables//--
local EventsFolder = ReplicatedStorage.Events
local CoinEvent = EventsFolder.CoinEvent
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local LeaderStats = Player:WaitForChild("leaderstats")
local CoinVal = LeaderStats.Coins
local PlayerGui = Player.PlayerGui
local MainGui = PlayerGui:WaitForChild("MainGui")
local Coins = MainGui.Coins
local CoinsFolder = workspace.Coins
local CoinDisplay = Coins.CoinDisplay
--//Function//--
for __, Coin in pairs(CoinsFolder:GetChildren()) do
	local Sparkles = Coin.Sparkles
	local Light = Coin.PointLight
	local Collect = Coin.Collect
	local function onTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			local PlayerHit = Players:GetPlayerFromCharacter(Hit.Parent)
			if PlayerHit == nil then
				return
			end
			CoinEvent:FireServer(CoinVal, Coin, Sparkles, Light, Collect)
		end
	end
	Coin.Touched:Connect(onTouched)
end
-----------------------------------------------------
while true do
	CoinDisplay.Text = "x"..CoinVal.Value
	task.wait()
end
-----------------------------------------------------

Server

local function onCoinEvent(Player, CoinVal, Coin, Sparkles, Light, Collect)
	Coin.CanTouch = false
	Collect:Play()
	Light:Destroy()
	Sparkles.Enabled = true
	Coin.Transparency = 1
	Collect:Play()
	Sparkles:Emit()
	CoinVal.Value = CoinVal.Value + 1
	task.wait(0.5)
	Coin:Destroy()
end

1 Like

Dude it’s because of the Coin.Touched event. You’re having multiple body parts touching the coin multiple times before it was destroyed

local function onTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") and not Coin:GetAttribute("Touched") then 
			local PlayerHit = Players:GetPlayerFromCharacter(Hit.Parent)
			if PlayerHit == nil then
				return
			end
            Coin:SetAttribute("Touched", true)
			CoinEvent:FireServer(CoinVal, Coin, Sparkles, Light, Collect)
		end
	end

I’ve added some things to your function. When a player first touches the coin, the coin will be given a Touched attribute so that the event won’t fire repeatedly

1 Like

Actually for some reason putting CanTouch = false on both the Server and Client fixed this. But now there’s a problem with the Item Blocks… sometimes when i test the game it says Left is not a valid member of Model "Workspace.ItemBlocks.ItemBlock" , and i mean SOMETIMES it does that. But i don’t know what’s causing it!

Client

--///Services//--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--//Variables//--
local EventsFolder = ReplicatedStorage.Events
local IBEvent = EventsFolder.ItemBlockEvent
local Player = Players.LocalPlayer
local LeaderStats = Player:WaitForChild("leaderstats")
local IBFolder = workspace.ItemBlocks
local CoinVal = LeaderStats.Coins
--//Function//--
for __, Block in pairs(IBFolder:GetChildren()) do
	local Left = Block.Left
	local Right = Block.Right
	local Center = Block.Center
	local Hitbox = Block.Hitbox
	local HitS = Hitbox.HitS
	local Collect = Hitbox.Collect
	local Light = Center.SpotLight
	local Sparkles = Center.Sparkles
	local function onTouched(Hit)
		if Hit and Hit.Parent:FindFirstChild("Humanoid") then
			local PlayerHit = Players:GetPlayerFromCharacter(Hit.Parent)
			if PlayerHit == nil then
				return
			end
			Hitbox.CanTouch = false
			IBEvent:FireServer(CoinVal, Block, Left, Right, Center, Hitbox, HitS, Collect, Light, Sparkles)
		end
	end
	Hitbox.Touched:Connect(onTouched)
end

Server

local function onIBEvent(Player, CoinVal, Block, Left, Right, Center, Hitbox, HitS, Collect, Light, Sparkles)
	Collect:Play()
	Hitbox.CanTouch = false
	Sparkles.Enabled = true
	Light:Destroy()
	HitS:Play()
	Collect:Play()
	Left:Destroy()
	Right:Destroy()
	Center.BrickColor = BrickColor.new("Dark orange")
	CoinVal.Value = CoinVal.Value + 5
	local BlockTInfo = TweenInfo.new(0.25, Enum.EasingStyle.Bounce, Enum.EasingDirection.In)
	local TweenUp = TweenService:Create(Center, BlockTInfo, {CFrame = Center.CFrame + Vector3.new(0, 1, 0)})
	local TweenDown = TweenService:Create(Center, BlockTInfo, {CFrame = Center.CFrame - Vector3.new(0, 0.5, 0)})
	TweenUp:Play()
	task.wait(0.4)
	Sparkles:Destroy()
	TweenDown:Play()
end

Then use WaitForChild. When u try to access something at the start of a localscript always use waitforcgild in case they havent load yet

Thanks, that seems to have fixed everything.

UPDATE : For some reason sometimes this happens?? Why? What the heck?

1 Like

Bump.‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎

Bump.‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎