**(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 ![]()