Why does this seem to only work once? (.Touched Event)

Hi, i’m currently making a .Touched Event to be able to pass an object to another player(and highlight instance). I finished making the event and it seems to work, but only once :smiling_face_with_tear: i looked in the output and there are no errors it just keeps printing the first one who the .Touched Event fires on.

Char = the player or whoever the Hot Potato holder is
foundchar = the player thats been touched by the Char

All help is appreciated, this is also TIME URGENT so please feel free for any suggestions or head-ups!

Server Script(Located in Server Script Service):

	--{Touched Function}--
	local char = HotPotatoHolder.Character
	
	for _, v in pairs(char:GetChildren()) do
		if v:IsA("BasePart") or v:IsA("Part") or v:IsA("MeshPart") then
			v.Touched:Connect(function(hit)
				if Players:GetPlayerFromCharacter(hit.Parent) and canpass == true then
					canpass = false
					local foundchar = hit.Parent
					
					HotPotato.Parent = foundchar
					Highlight.Parent = foundchar
					
					HotPotatoHolder = Players:GetPlayerFromCharacter(foundchar)
					print(HotPotatoHolder)
					
					task.wait(1)
					canpass = true
				end
			end)
		end
	end

This is because the for loop is only running once. I’d recommend running it in a coroutine loop like this.

couroutine.wrap (function()
     while true do
     for _, v in pairs(char:GetChildren()) do
		if v:IsA("BasePart") or v:IsA("Part") or v:IsA("MeshPart") then
			v.Touched:Connect(function(hit)
				if Players:GetPlayerFromCharacter(hit.Parent) and canpass == true then
					canpass = false
					local foundchar = hit.Parent
					
					HotPotato.Parent = foundchar
					Highlight.Parent = foundchar
					
					HotPotatoHolder = Players:GetPlayerFromCharacter(foundchar)
					print(HotPotatoHolder)
					
					task.wait(1)
					canpass = true
				end
			end)
		end
	end
end
task.wait()
end)
2 Likes

Ok, Ill try this thanks for the suggestion, but it was printing more than once signaling it was firing more than once; so other than the printing everything else seems like its firing once

(UPDATE 1) Now it doesn’t work at all, no errors, nothing.

Hope that couroutine works. Maybe try seeing if the player touched the hotp and work the logic from that point of view.

1 Like

To be honest I feel like it’s on Roblox end. I get the prints of the players name so .Touched might not be accurate. Do you have any alternatives I could use?(excluding :GetTouchingParts)

i’d recommend making the for loop a function, and every time the hotpotatoholder changes refire the function instead of spam looping like that, it’ll save you a lot of memory

2 Likes

It was printing more than once because you had it print for every time it loops throught the table (getchildren)

If that makes sense

1 Like

I think I see the issue now, the conditional if statement in the touched event doesn’t continue because canpass’ default value is false. Make sure to manually set it true for the first person who gets the hot potato.

As in saving memory I’d recommend using @Ziraun advice to connect the touched event only to the potato and remove the coroutine and the for loop

1 Like

Thankyou very much do you have an idea of how I would imply that, i cant refire everytime the HotPotatoHolder changes because this is the part that changes it? Thanks again these relies help a lot :slightly_smiling_face:

Yes, I already initially set canpass to true

Here is the whole function script incase its hard to work with the shortened one:

local function StartRound()
	local timeleft

	--[[{If one doesnt win then we pick another one}-- Disabled for now for .Touched Testing
	if #PlayersInRound == 1 then
		InfoLabel.Text = PlayersInRound[1].Name.." won the game!"
		task.wait(2.5)

		for i,v in pairs(PlayersInRound) do
			v.Character:MoveTo(LobbySpawn.Position)
			table.clear(PlayersInRound)
			print("Done")
		end

		RoundCountdown()
	end
--]]

	--Picking a random holder
	HotPotatoHolder = PlayersInRound[math.random(1, #PlayersInRound)]

	--{Cloning Visual Effects & Tool}--
	local HotPotato = script.HotPotato:Clone()
	HotPotato.Parent = HotPotatoHolder.Character

	local Highlight = script.Highlight:Clone()
	Highlight.Parent = HotPotatoHolder.Character

	--{Touched Function}--
	local char = HotPotatoHolder.Character
	local canpass = true

	for _, v in pairs(char:GetChildren()) do
		if v:IsA("BasePart") or v:IsA("Part") or v:IsA("MeshPart") then
			v.Touched:Connect(function(hit)
				if Players:GetPlayerFromCharacter(hit.Parent) and canpass == true then
					canpass = false
					local foundchar = hit.Parent

					HotPotato.Parent = foundchar
					Highlight.Parent = foundchar

					HotPotatoHolder = Players:GetPlayerFromCharacter(foundchar)
					print(HotPotatoHolder)

					task.wait(1)
					canpass = true
				end
			end)
		end
	end
--Old .Touched Bound to delete
				--[[if hit ~= nil and hit.Parent.Name ~= char.Name and Players:GetPlayerFromCharacter(hit.Parent) and canpass == true then
					canpass = false
					
					
					HotPotatoHolder = Players:GetPlayerFromCharacter(hit.Parent)

					HotPotato.Parent = hit.Parent
					Highlight.Parent = hit.Parent
					
					print("Passed Highlight and Hot Potato to "..hit.Parent.Name)
					task.wait(1)
					canpass = true
				else
					return
				end
				--]]

	for i = 10, 0, -1 do
		timeleft = i
		InfoLabel.Text = HotPotatoHolder.Name.." has the Hot Potato!!.."..timeleft
		task.wait(1)
	end

	--{Killing the holder & removing from table when time's up}--

	HotPotato:Destroy()
	Highlight:Destroy()
	HotPotatoHolder.Character:WaitForChild("Humanoid"):TakeDamage(999)

	table.remove(PlayersInRound, PlayersInRound[HotPotatoHolder])
	StartRound()

end

Just like what @Ziraun Mentioned, you should put the loop inside of a function and refresh it. (Also disconnecting the event for less memory consumption.)

--Note that this function is under the StartRound function
local function RefreshHolder(char)
  for _, v in ipairs(char:GetChildren()) do
    if v:IsA("BasePart") == nil then return end
    local connection = v.Touched:Connect(function(hit)
      if hit:IsA("BasePart") and canpass then
        local foundplr = game.Players:GetPlayerFromCharacter(hit.Parent)
        if foundplr then
            canpass = false
            RefreshHolder(foundplr.Character)
            HotPotato.Parent = foundplr.Character
            Highlight.Parent = foundplr.Character
            task.wait(1)
            canpass = true
            connection:Disconnect() --Idk if you can disconnect an event inside that event function, may try
        end
      end
    end)
  end
end
1 Like