Chasing class[Pathfinder] - Improvement Needed

Hi, I made a chasing class, that is incomplete right now. I just wanted to see how’s my progress so far. Any memory leaks, or performance issues. ModuleScript code:

local Pathfinder = {

};

local class = {

};

class.__index = class

-- // Services // 

local pathfindingSer = game:GetService("PathfindingService")
local runSer = game:GetService("RunService")
local players = game:GetService("Players")

-- // Functions //

function Pathfinder.Wait(x)
	x = tonumber(x) or (1/30)
	local s = os.clock()
	while (os.clock() - s) < x do
		runSer.Heartbeat:Wait()
	end
	return (os.clock()-s)
end

local function canSeeTheTarget(eye,target,ignoreList)
	if not (eye) or not (target) or (eye and not (eye.Parent)) or (target and not (target.Parent)) then return end
	local toTarget = (target.Position - eye.Position)
	local params = RaycastParams.new()
	-- print(l)
	local l = ignoreList and {} or {eye.Parent}
	for _, t in pairs(ignoreList ) do
		if (t:IsA("Humanoid")) then
			if not (t) or (t and not (t.Parent)) then continue end
			local r = t.RootPart
			if not (r) or (r and not (r.Parent)) then continue end
			table.insert(l,#l+1,r.Parent)
		end
	end
	params.FilterDescendantsInstances = l
	params.FilterType = Enum.RaycastFilterType.Blacklist
	local raycast_Result = workspace:Raycast(eye.Position,(toTarget.Unit * toTarget.Magnitude),params);
	if (raycast_Result) then
		--[[
				local found = workspace:FindFirstChild("debug.new()" .. eye.Parent.Name);
				if not (found) then
					local part = Instance.new("Part")
					part.Name = "debug.new()" .. eye.Parent.Name;
					part.Transparency = 0.5
					part.Material = Enum.Material.Neon
					part.Anchored = true
					part.CanCollide = false
					part.Color = Color3.fromRGB(255, 0, 0)
					part.Size = Vector3.new(.5,.5,toTarget.Magnitude);
					part.Parent = workspace
				else
					-- Just CFrame
					found.Size = Vector3.new(.5,.5,toTarget.Magnitude)
					local cf = CFrame.lookAt(eye.Position,raycast_Result.Position)*CFrame.new(0,0,-toTarget.Magnitude/2);
					found.CFrame = cf
				end
		--]]
		-- print(math.abs(eye.Position.Y - target.Position.Y));
		return raycast_Result.Instance:IsDescendantOf(target.Parent) and math.abs(target.Position.y - eye.Position.y) < 3;
	end
end

local function isInstance(ob)
	return typeof(ob) == "Instance"
end

local function getNearestRig(from,ignoreList : table?)
	if not (isInstance(from)) then	
		return
	end
	local rigRoot = from.RootPart
	if not (rigRoot) or (rigRoot and not (rigRoot.Parent)) then return end
	local nearest,nearestDist
	local descendants = {};
	for _, t in pairs(workspace:GetDescendants()) do
		if (t:IsA("Humanoid")) then
			local index_ = table.find(ignoreList,t)
			if (index_) then continue end
			table.insert(descendants,#descendants+1,t);
		end
	end
	for _, descendant in pairs( descendants ) do
		if (descendant:IsA("Humanoid")) then
			-- Humanoid spotted
			local root_part = descendant.RootPart;
			if not (root_part) then continue end; -- RootPart doesn't exist in the humanoid
			if (nearest and nearestDist) then
				local temporary = (root_part.Position - rigRoot.Position).magnitude
				if (temporary <= nearestDist) then
					nearestDist = temporary
					nearest = root_part
				end
			else
				nearestDist = (root_part.Position - rigRoot.Position).magnitude
				nearest = root_part;
			end
		end
	end
	return {nearest,nearestDist};
end 

-- // Class functions //

function Pathfinder.new(humanoids : table?)
	if not (humanoids) then return end
	if (typeof(humanoids) ~= "table") then return end
	-- if not (getRigAuto) then return end
	local attacked = Instance.new("BindableEvent");
	attacked.Name = "Attacked";
	local self = setmetatable({
		_humanoids = humanoids;
		_target = false;
		_isChasing = false;
		_attacked = attacked;
		Attacked = attacked.Event;
		_rbx_signals = {};
	},class)
	return self
end

function class:getTarget()
	return self._target
end

function class:getHumanoid()
	return self._humanoid
end

function class:getIgnoreList()
	return self._ignoreList;
end

function class:setIgnoreList(list)
	if not (list) then return end
	if not (typeof(list) == "table") then return end
	self._ignoreList = list
	return self;
end

function class:setTarget(humanoid : Instance?)
	if not (humanoid) then return end 
	if not (isInstance(humanoid)) or (isInstance(humanoid)) and not (humanoid:IsA("Humanoid")) then
		return
	end
	self._target = humanoid
	return self;
end

function class:startChasing()
	if (self._isChasing) then return end
	-- Start chasing now
	self._isChasing = true;
	local _humanoids = self._humanoids;
	while (self._isChasing) do
		-- Eligible for them to chase
		for index, currentHumanoid in pairs(_humanoids) do
			-- So, first of all. Find the nearest and get their path.
			-- Also, check if the humanoid even exists.
			local thread = coroutine.wrap(function()
				if not (currentHumanoid) then return end -- Skips this turn
				local chasingInformation = getNearestRig(currentHumanoid,_humanoids)
				local target = chasingInformation[1]
				if not (target) or (target and not (target.Parent)) then return end
				-- Compute the path, and get the waypoints.
				local root = currentHumanoid.RootPart;
				if not (root.Anchored) then
					root:SetNetworkOwner(nil)
				end
				if (canSeeTheTarget(root,target,_humanoids)) then
					-- Current humanoid can see the nearest target
					currentHumanoid:MoveTo(target.Position)
				else
					local extentsSize = currentHumanoid.Parent:GetExtentsSize()
					local path = pathfindingSer:CreatePath({
						AgentRadius = extentsSize.Z/2;
						AgentHeight = extentsSize.Y;
						AgentCanJump = true;
					})
					path:ComputeAsync(root.Position,target.Position) -- Compute the path
					local waypoints = path:GetWaypoints() -- Get the waypoints
					for x, waypoint in pairs(waypoints) do
						if (waypoint.Action == Enum.PathWaypointAction.Jump) then
							currentHumanoid.Jump = true;
						end
						currentHumanoid:MoveTo(waypoint.Position)
						local timeOut = currentHumanoid.MoveToFinished:Wait(3)
						if canSeeTheTarget(root,target,_humanoids) then
							currentHumanoid:MoveTo(target.Position)
							break
						end
						if not (timeOut) then
							currentHumanoid.Jump = true
							break
						end
		
					end
				end
			end)
			thread()	
		end
		runSer.Heartbeat:Wait()
	end
end

function class:stopChasing()
	if not (self._isChasing) then return end
	-- Stop chasing now
	self._isChasing = false;
end

return Pathfinder

I would love it if any of you reads it and helps me in improving :smiley:

1 Like

Any responses? Been waiting. pls read