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 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)
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
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
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
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
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