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