Infinite yield possible on 'Workspace:WaitForChild("Humanoid")'

Hello,

I am making a go-cart for a friend but for some reason it keeps giving me the error “Infinite yield possible on ‘Workspace:WaitForChild(“Humanoid”)’”

This is my script:

local event = script.Parent.OnEquip

local tool = script.Parent

local debounce = false

event.OnServerEvent:Connect(function(player)
	local char = player.Character
	
	local hum = char:FindFirstChild("Humanoid")
	
	hum.WalkSpeed = 45
	
	local anim = tool.Idle
	local idle = hum:LoadAnimation(anim)
	idle:Play()
	
	tool.Handle.IdleMusic:Play()
	
	tool.Handle.Touched:Connect(function(hit)
		if hit.Parent ~= tool.Parent and debounce == false then
			local player = hit.Parent
			local char = player
			debounce = true
			local humanoid = char:WaitForChild("Humanoid")
			humanoid:TakeDamage(99900)
			wait(0.2)
			debounce = false
		end
	end)
	tool.Unequipped:Connect(function()
		hum.Walkspeed = 16
		tool.Handle.IdleMusic:Stop()
	end)
end)


I am still unsure on how to fix this. I’ve tried FindFirstChild, but that didn’t work.

My local script is just a simple script that triggers the event. Nothing else. But if you want to see it, here it is:

local event = script.Parent:WaitForChild("OnEquip")

local tool = script.Parent

tool.Equipped:Connect(function(player)
	event:FireServer()
	print("Test 1 Passed")
end)

Anything helps.

3 Likes

ALSO:

The tool keeps spawning only in one spot when I equip it. and I want to stop that. Any reason why its doing that?

I equip it then I get teleported to the spot I was editing it in. It is fine after my character is done falling down.

1 Like

You set char = player and then call WaitForChild(“Humanoid”). The player does not have a Humanoid inside of it unless you added one.

1 Like

" Character is not a valid member of Model “Workspace.Dummy” "

You set “char” to the player who fired the remote. If you are trying to damage the dummy then “char” should equal the dummy. Try char = hit.Parent

Try to change the name of one of the variables. You have 2 variables with the same name

same with these ones

image

Change that to

local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
if plr then
--rest of the code
end

The hit arguement of the touched event could be a part in the workspace and since your code says player = hit.Parent, that would refer the actual workspace

The code above checks if the parent of the part detected is a player

Players.squaredsnow.Backpack.Da Whip.Script:7: attempt to index nil with ‘Parent’

Update:
I changed my scripts so theyre more easier to read, I can add more later. But heres my local script:

local event = script.Parent:WaitForChild("OnEquip")

local tool = script.Parent

tool.Equipped:Connect(function(player)
	tool.Handle.Touched:Connect(function(hit, plr)
		if hit.Parent ~= tool.Parent then
			event:FireServer()
			print("Test 1 Passed")
		end
	end)
end)

and heres my serverscript:

local event = script.Parent.OnEquip

local tool = script.Parent


event.OnServerEvent:Connect(function(player, hit)
	local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
	if plr then
		local char = player.Character
		
		char:WaitForChild("Humanoid"):TakeDamage(99999)
	end
end)

And heres my error that keeps getting spammed in my output:

 Players.squaredsnow.Backpack.Da Whip.Script:7: attempt to index nil with 'Parent'

Ah, touched events don’t fire in local scripts

tool.Handle.Touched:Connect(function(hit, plr)
		if hit.Parent ~= tool.Parent then
			event:FireServer()
			print("Test 1 Passed")
		end
	end)

Responding to the original post

The reason it’s yielding infinitely is that there’s no guarantee that the parent of any part you hit has a humanoid (what if you struck the baseplate for example?). Use the presence of a humanoid as a check to determine whether hit.Parent is a valid character.

I’d restructure the code to look like this:

tool.Handle.Touched:Connect(function(hit)
		local char = hit.Parent
		local humanoid = char:FindFirstChild("Humanoid") --Define the humanoid early
		if humanoid and char ~= tool.Parent and debounce == false then --Check if the humanoid exists before proceeding
			debounce = true
			humanoid:TakeDamage(99900)
			wait(0.2)
			debounce = false
		end
	end)

Note: This solution doesn’t use WaitForChild, but since the humanoid loads in a character extremely quickly, it isn’t a big deal if you hit a character who just spawned and they get skipped because they don’t have a humanoid yet.

3 Likes

Oh, can I just put player in the server script and get rid of the event?

Exactly, call the touched event on the server and use @fungi3432’s suggestions

Worked. Thank you so much!

yay i have to add more characters to say thank you…

local tool = script.Parent
local handle = tool.Handle
local idleSound = handle.IdleMusic
local anim = tool.Idle

local debounce = false
local touchedConnection = nil

tool.Equipped:Connect(function()
	local character = tool.Parent
	local humanoid = character.Humanoid
	humanoid.WalkSpeed = 45
	
	local idleTrack = humanoid:LoadAnimation(anim)
	repeat task.wait() until idleTrack.Length > 0
	idleTrack:Play()
	idleSound:Play()

	touchedConnection = handle.Touched:Connect(function(hit)
		if debounce then
			return
		end
		
		local hitModel = hit:FindFirstAncestorOfClass("Model")
		if hitModel then
			local hitHuman = hitModel:FindFirstChildOfClass("Humanoid")
			if hitHuman then
				debounce = true
				hitHuman:TakeDamage(math.huge)
				task.wait(0.25)
				debounce = false
			end
		end
	end)
end)

tool.Unequipped:Connect(function()
	if touchedConnection then
		touchedConnection:Disconnect()
		touchedConnection = nil
	end
	
	local player = tool:FindFirstAncestorOfClass("Player")
	local character = player.Character
	local humanoid = character.Humanoid
	humanoid.Walkspeed = 16
	idleSound:Stop()
end)

I’d recommend getting rid of that local script & RemoteEvent instance and containing this all within a single server script, your current implementation is going to lead to memory leaks because you’re connecting events and then not disconnecting them when they are no longer necessary.

local tool = script.Parent
local handle = tool.Handle
local idleSound = handle.IdleMusic
local anim = tool.Idle
local idleTrack = nil

local debounce = false
local touchedConnection = nil

tool.Equipped:Connect(function()
	local character = tool.Parent
	local humanoid = character.Humanoid
	humanoid.WalkSpeed = 45
	
	if not idleTrack then
		idleTrack = humanoid:LoadAnimation(anim)
	end
	
	repeat task.wait() until idleTrack.Length > 0
	idleTrack:Play()
	idleSound:Play()

	touchedConnection = handle.Touched:Connect(function(hit)
		if debounce then
			return
		end

		local hitModel = hit:FindFirstAncestorOfClass("Model")
		if hitModel then
			local hitHuman = hitModel:FindFirstChildOfClass("Humanoid")
			if hitHuman then
				debounce = true
				hitHuman:TakeDamage(math.huge)
				task.wait(0.25)
				debounce = false
			end
		end
	end)
end)

tool.Unequipped:Connect(function()
	if touchedConnection then
		touchedConnection:Disconnect()
		touchedConnection = nil
	end

	local player = tool:FindFirstAncestorOfClass("Player")
	local character = player.Character
	local humanoid = character.Humanoid
	humanoid.Walkspeed = 16
	idleSound:Stop()
	if idleTrack then
		idleTrack:Stop()
	end
end)

I see you wanted the animation to start/stop in another thread so I’ve added that change as well.