Respawn System for NPC - Cant find HumanoidRootPart after the respawn

The npc’s behavior is to runaway when the npc detects a gun. The logic works fine when its initially spawned but when it gets respawned it cant find the HumanoidRootPart and this is what prints in the output:

05:31:21.651 Infinite yield possible on ‘Civilian:WaitForChild(“HumanoidRootPart”)’ - Studio
05:31:21.652 Stack Begin - Studio
05:31:21.652 Script ‘Workspace.Civilian.AI’, Line 113 - function canSeePlayer - Studio
05:31:21.652 Script ‘Workspace.Civilian.AI’, Line 204 - Studio
05:31:21.652 Stack End - Studio

Respawn Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")

local civilianTemplate = ReplicatedStorage:WaitForChild("Civilian")

local spawnsFolder = Workspace:WaitForChild("Spawns")

-- Keep track of the civilians
local civilians = {}


local function resetCivilianBehavior(civilian)
	-- Wait for Humanoid and HumanoidRootPart to ensure they're loaded
	local humanoid = civilian:WaitForChild("Humanoid")
	local humanoidRootPart = civilian:WaitForChild("HumanoidRootPart")

	if not humanoidRootPart then
		warn("HumanoidRootPart not found in resetCivilianBehavior!")
		return
	end

	-- Reset health if the civilian has a Humanoid
	humanoid.Health = humanoid.MaxHealth 

	-- Re-enable or reset custom scripts like FollowPlayerScript 
	for _, script in pairs(civilian:GetChildren()) do
		if script:IsA("Script") or script:IsA("LocalScript") then
			script.Disabled = true
			script.Disabled = false 
		end
	end
end

local function spawnCivilianAtPart(spawnPart)
	-- Clone the Civilian from the template
	local clonedCivilian = civilianTemplate:Clone()

	-- Ensure the PrimaryPart is set before spawning
	local humanoidRootPart = clonedCivilian:FindFirstChild("HumanoidRootPart")
	if humanoidRootPart then
		clonedCivilian.PrimaryPart = humanoidRootPart
	else
		warn("HumanoidRootPart is missing in the cloned civilian!")
		return -- Exit the function early if no HumanoidRootPart exists
	end

	-- Set the cloned Civilian's position to the spawn part's position
	clonedCivilian:SetPrimaryPartCFrame(spawnPart.CFrame)

	-- Parent the cloned Civilian to the Workspace 
	clonedCivilian.Parent = Workspace

	-- Reset the civilian's behavior or reinitialize scripts
	resetCivilianBehavior(clonedCivilian)

	-- Add the civilian to the civilians table for tracking
	civilians[spawnPart] = clonedCivilian

	-- Check if the civilian has a Humanoid to detect when it dies
	local humanoid = clonedCivilian:FindFirstChildOfClass("Humanoid")
	if humanoid then
		humanoid.Died:Connect(function()
			print("Civilian died! Checking parts before respawn...")

			-- Before respawn, check if the necessary parts are missing
			if not clonedCivilian:FindFirstChild("HumanoidRootPart") then
				warn("HumanoidRootPart is missing before respawn!")
			end

			-- Destroy the previous civilian (clean up)
			clonedCivilian:Destroy()

			-- Wait a short time before spawning the next civilian at the same spot
			wait(2)
			spawnCivilianAtPart(spawnPart) 
		end)
	end
end

-- Function to spawn civilians at all spawn parts
local function spawnCiviliansForAllParts()
	local spawnParts = spawnsFolder:GetChildren()

	if #spawnParts > 0 then
		for _, spawnPart in ipairs(spawnParts) do
			spawnCivilianAtPart(spawnPart)
		end
	else
		warn("No spawn parts found in the Spawns folder!")
	end
end

spawnCiviliansForAllParts()

NPC Script

local npc = script.Parent

local function canSeePlayer(player)
	-- Add a timeout for the NPC's HumanoidRootPart
	local humanoidRootPart = npc:WaitForChild("HumanoidRootPart") 
	if not humanoidRootPart then
		warn("HumanoidRootPart not found in canSeePlayer function!")
		return false -- Return false if the HumanoidRootPart isn't found
	end

	local playerHumanoidRootPart = player.Character:WaitForChild("HumanoidRootPart")
	if not playerHumanoidRootPart then
		warn("Player's HumanoidRootPart not found!")
		return false
	end

	local npcPosition = humanoidRootPart.Position
	local direction = (playerHumanoidRootPart.Position - npcPosition).unit
	local ray = Ray.new(npcPosition, direction * 100)
	local hit, position = workspace:FindPartOnRay(ray, npc)

	return hit and hit:IsDescendantOf(player.Character)
end

local function onPlayerAdded(player)
	player.CharacterAdded:Connect(function(character)
		character.ChildAdded:Connect(function(child)
			if child:IsA("Tool") and (child.Name == "Pistol" or child.Name == "AK-47") then
				if not runningAway and canSeePlayer(player) then
					runAwayFrom(player)
				end
			end
		end)
		character.ChildRemoved:Connect(function(child)
			if child:IsA("Tool") and (child.Name == "Pistol" or child.Name == "AK-47") then
				wait(runDelay)
				runningAway = false
			end
		end)
	end)
end

Try out having the NPC script print(npc) at the start of the canSeePlayer function? There’s a chance that the parent is getting messed up, in addition, I’d check in the explorer while running the game to see if the erroring npcs actually still have humanoidrootparts.

Alright I tried it and it does print out the npc and it still has the rootpart but I still get Infinite yield.

if you change
local humanoidRootPart = npc:WaitForChild("HumanoidRootPart")
to
local humanoidRootPart = npc:WaitForChild("HumanoidRootPart", 10)
does your “HumanoidRootPart not found in canSeePlayer function!” warning print?

yes the warning does print with the (“HumanoidRootPart”, 10)
16:57:02.866 HumanoidRootPart not found in canSeePlayer function! - Studio

at the start of the canseeplayer function, can you do a
print(npc.Name) print(npc:GetChildren()) and post a ss of what it prints? (It should print a table that you can expand in the output panel, make sure that it’s expanded)

Not sure why it cant locate the descendants when it respawns
for the initial spawn

17:02:07.937 Civilian - Server - AI:112
17:02:07.937 ▼ {
[1] = Head,
[2] = HumanoidRootPart,
[3] = Left Arm,
[4] = Left Leg,
[5] = Right Arm,
[6] = Right Leg,
[7] = Torso,
[8] = Humanoid,
[9] = Pants,
[10] = Shirt,
[11] = Body Colors,
[12] = MeshPartAccessory,
[13] = New Hair,
[14] = SlouchyBeanie_BLU_Accessory,
[15] = AI,
[16] = Briefcase
} - Server - AI:112

for the second spawn

  17:02:22.634  Civilian  -  Studio
  17:02:22.634  {}  -  Studio

This means the model got cleared of its descendants between death and respawn. Instead of respawning the civilians as you are now, I would simply destroy the civilians and completely respawn them from scratch.

I thought I was already doing that in the respawn script. I destroy the previous npc and copy it from replicated storage into workspace.

Oh my bad I mistook the reset behavior function as the respawning one.
is warn("HumanoidRootPart not found in resetCivilianBehavior!") or warn("HumanoidRootPart is missing in the cloned civilian!") printing to your console when they respawn?
Also, what are the new civilian npcs that respawn looking like? Do they load in at all? Just standing there?

no nothing is printing from the respawn script and the npc seems to be walking to waypoints fine its just whenever the player pulls out a gun where I getInfinite yield possible. Not sure why its happening but when it initially spawns everything is fine

Does the npc still respond correctly? Or is it stalling while the inf yield error happens? (I say this because it is possible that there are dead npcs which have empty models that are throwing the error)