(SOLVED!) Creating thread for zombie module breaks it

**(SOLVED!!!)**I’m trying to make a thread every time a zombie pathfinds to a specific place on the map, so I can loop through all zombies and apply this functionality at the same time for each zombie.

Whenever I use the threadSpawn() function in my OOP zombie module at this specific spot, instead of the zombie pathfinding to the specific point, it just wanders left and right in the same 2 directions forever, and the original goal of making a thread for each zombie doesn’t even work because only 1 zombie even moves at all. No errors either.

I’ve tried looking if I made my thread function wrong but I’m not sure why it isn’t working, since I used it in other parts of the module and it seems to be working fine, it’s just using it in this specific point of the code.

Full Module if you need it
--Services
local CollectionService = game:GetService("CollectionService")
local PathfindingService = game:GetService("PathfindingService")
local ServerStorage = game:GetService("ServerStorage")

--Modules
local Modules = ServerStorage:WaitForChild("Modules")

local GeneralModules = Modules:WaitForChild("General")
local EntranceClass = require(GeneralModules:WaitForChild("Entrance"))


--Main module
local zombie = {}
zombie.__index = zombie


--Setting up zombie
function zombie.new(char: Model, health: number, breakSpeed: number, damage: number, attackRange: number, detectRange: number, smoothness: number,position: CFrame)
	
	--Setting up Metatable
	local self = setmetatable({}, zombie)
	
	--Setting up values and variables
	zombie.char = char
	zombie.root = char:FindFirstChild("HumanoidRootPart")
	zombie.humanoid = char:FindFirstChild("Humanoid") :: Humanoid
	zombie.head = char:FindFirstChild("Head")
	zombie.torso = char:FindFirstChild("Torso")
	
	zombie.target = nil
	
	--Animations
	zombie.animator = zombie.humanoid:FindFirstChild("Animator")
	zombie.grabAnim = zombie.animator:LoadAnimation(zombie.char:FindFirstChild("Grab"))
		
	--Properties
	zombie.health = health
	zombie.humanoid.MaxHealth = health
	zombie.humanoid.Health = health
	
	zombie.breakSpeed = breakSpeed
	
	zombie.damage = damage
	zombie.attackRange = attackRange
	zombie.detectRange = detectRange
	zombie.smoothness = smoothness
	
	--Thread variables
	zombie.threads = {}
	
	
	zombie.__type = "Zombie"
	
	--Run code
	zombie.humanoid:AddTag("Zombie")
	zombie:position(position)
	
	
	return self
	
end


------------------------------------------------------------
--METAMETHODS


------------------------------------------------------------
--MOVEMENT FUNCTIONS


--Move zombie to position instantly
function zombie:position(position: CFrame)
	
	if self.__type ~= "Zombie" then return end

	
	self.root:PivotTo(position)
	
	
	return self
	
end


--------------------------------------------
--AI FUNCTIONS--


--Entrance Functions--

--Break plank
function zombie:BreakPlanks(Entrance)
	
	repeat task.wait(self.breakSpeed) Entrance:Break()
		until (Entrance.currentPlanks == 0) or (zombie.humanoid.Health <= 0)
	
end

--Find nearest entrance
function zombie:MoveToNearestEntrance(Entrances)
	
	if self.__type ~= "Zombie" then return end

	--Variables
	local target = nil
	local dist = self.detectRange
	local entrance = nil
	
	--Finding entrance
	for _, entranceObject in pairs(Entrances) do
		local breakZone = entranceObject.breakZone
		if (breakZone) and (self.checkDist(breakZone, self.root) < dist) then
			dist = self.checkDist(breakZone, self.root)
			target = breakZone
			entrance = entranceObject
		end
	end
	
	self.target = target
	
	
	--Moving to entrance--
	
	--Creating path
	self.threadSpawn(self, function()
		
		local path = PathfindingService:CreatePath()
		path:ComputeAsync(self.root.Position, self.target.Position)

		local waypoints = path:GetWaypoints()
		local currentTarget = self.target

		--Setting up pathfinding
		if path.Status == Enum.PathStatus.Success then
			for i, waypoint in pairs(waypoints) do

				-----------------
				local part = Instance.new("Part")
				part.CanCollide = false
				part.Anchored = true
				part.Material = "Neon"
				part.BrickColor = BrickColor.new("Royal purple")
				part.Position = waypoint.Position
				part.Size = Vector3.new(1,1,1)

				-----------------

				--Creating waypoints and moving zombie there
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					self.humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				else
					self.humanoid:MoveTo(waypoint.Position)

					self.threadSpawn(self, function()
						task.wait(0.5)
						if self.humanoid.WalkToPoint.Y > self.root.Position.Y then
							self.humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
						end
					end)
				end

				--Makes sure zombie walking is correct
				self.humanoid.MoveToFinished:Wait()

				--Making sure tracking works
				if not self.target then
					print("Lost target")
					break
				elseif (self.checkDist(currentTarget, waypoints[#waypoints]) > self.smoothness) or currentTarget ~= self.target then
					print("?")
					self:MoveToEntrance()
					break
				end

			end

			--Breaking Planks--
			self:BreakPlanks(entrance)

		else
			print("Path unable to be computed")
			zombie:removeZombie()
		end
		
	end)
	
	
	
	return self
	
end



----------------------------------
--Pathfinding Functions--





--------------------------------------------
--UTILITY FUNCTIONS--


--Remove zombie
function zombie:removeZombie()

	if self.__type ~= "Zombie" then return end


	task.wait(5)
	
	--Close all threads
	for _, thread in pairs(self.threads) do
		coroutine.close(thread)
		thread = nil
	end
	
	self.char:Destroy()
	
	self = nil
	

	return self

end


--Check distance(NORMAL FUNCTION)
function zombie.checkDist(part1: Part | Vector3, part2: Part | Vector3): number
	if typeof(part1) ~= Vector3 then part1 = part1.Position end
	if typeof(part2) ~= Vector3 then part2 = part2.Position end

	return (part1 - part2).Magnitude
end


--Spawn thread
function zombie.threadSpawn(zombieObject, functionObject, ...)
	
	if zombieObject.__type ~= "Zombie" then return end
	
	
	local co = coroutine.wrap(functionObject)
	
	table.insert(zombieObject.threads, co)
	
	co(...)
	
end


------------------------------------------------------------


return zombie

Here’s the threadSpawn function:

--Spawn thread
function zombie.threadSpawn(zombieObject, functionObject, ...)
	
	if zombieObject.__type ~= "Zombie" then return end
	
	
	local co = coroutine.wrap(functionObject)
	
	table.insert(zombieObject.threads, co)
	
	co(...)
	
end

The point where it breaks the zombie:

--Creating path
	self.threadSpawn(self, function() --RIGHT HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		
		local path = PathfindingService:CreatePath()
		path:ComputeAsync(self.root.Position, self.target.Position)

		local waypoints = path:GetWaypoints()
		local currentTarget = self.target

		--Setting up pathfinding
		if path.Status == Enum.PathStatus.Success then
			for i, waypoint in pairs(waypoints) do

				-----------------
				local part = Instance.new("Part")
				part.CanCollide = false
				part.Anchored = true
				part.Material = "Neon"
				part.BrickColor = BrickColor.new("Royal purple")
				part.Position = waypoint.Position
				part.Size = Vector3.new(1,1,1)

				-----------------

				--Creating waypoints and moving zombie there
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					self.humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				else
					self.humanoid:MoveTo(waypoint.Position)

					self.threadSpawn(self, function()
						task.wait(0.5)
						if self.humanoid.WalkToPoint.Y > self.root.Position.Y then
							self.humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
						end
					end)
				end

				--Makes sure zombie walking is correct
				self.humanoid.MoveToFinished:Wait()

				--Making sure tracking works
				if not self.target then
					print("Lost target")
					break
				elseif (self.checkDist(currentTarget, waypoints[#waypoints]) > self.smoothness) or currentTarget ~= self.target then
					print("?")
					self:MoveToEntrance()
					break
				end

			end

			--Breaking Planks--
			self:BreakPlanks(entrance)

		else
			print("Path unable to be computed")
			zombie:removeZombie()
		end
		
	end)

Thanks :happy2:

(I fixed the class, so every object is an individual object) Hmmm, i think it’s something to do with editing the entire class