Heya there.
I’m done implementing raycasting into a pathfinding module so enemies will ONLY pathfind if necessary. It works as intended as if a ray constantly being shot at their head detects a wall, pathfind. The issue however is that the enemy will ignore the player and head straight to the objective. After reaching the objective, it’ll then begin to chase after players after entering their AggroRange. Another issue arises however.
For some reason, even getting out of their range, they’ll still target you. Although this assumes the player is 30 or more studs away from the enemy when it spawns as 30 or more close to it will just do the latter problem. Any solutions?
--[[SERVICES]]--
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
--[[MODULE]]--
local PathfindingModule = {}
function PathfindingModule.Pathfind(NPC, AggroRange)
--//Preperation
local Objective = game.Workspace:FindFirstChild("Crystal")
--Enemy
local RootPart = NPC.PrimaryPart
local Humanoid = NPC.Humanoid
local CharacterSize = NPC:GetExtentsSize()
RootPart:SetNetworkOwner(nil)
--//Pathfinding Agents
local PathfindingAgents = {
AgentRadius = (CharacterSize.X + CharacterSize.Z)/4,
AgentHeight = CharacterSize.Y,
AgentCanJump = true
}
--[[PATHFINDING]]--
local LookDirection = NPC.Head.CFrame.LookVector
local function FollowPath(Destination)
local RaycastingParams = RaycastParams.new()
RaycastingParams.FilterDescendantsInstances = {NPC, Objective}
RaycastingParams.FilterType = Enum.RaycastFilterType.Exclude
local RaycastResult = workspace:Raycast(NPC.Head.Position, LookDirection * 30, RaycastingParams)
if RaycastResult then
--//That's bad, the enemy detected something in front of it (Besides players, other enemies, or the objective, a wall.)
--//We can just pathfind it, however.
local NewPath = PathfindingService:CreatePath(PathfindingAgents)
NewPath:ComputeAsync(RootPart.Position,Destination)
if NewPath.Status == Enum.PathStatus.Success then
local Waypoints = NewPath:GetWaypoints()
for _, Waypoint in pairs(Waypoints) do
if Waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid.Jump = true
end
--//Visualize
local WaypointVisulize = Instance.new("Part",workspace)
WaypointVisulize.Size = Vector3.new(1,1,1)
WaypointVisulize.Anchored = true
WaypointVisulize.CanCollide = false
WaypointVisulize.Position = Waypoint.Position
Humanoid:MoveTo(Waypoint.Position)
local TimeOut = Humanoid.MoveToFinished:Wait(1)
if not TimeOut then
print("Path taking way too long. Recalculating.")
Humanoid:MoveTo(Objective.PrimaryPart.Position)
end
end
else
print("Pathfinding went wrong, sorry.")
end
else
--//That's good, enemy hasn't detected anything in front of it :3
Humanoid:MoveTo(Objective.PrimaryPart.Position)
end
--[[
--OLD
local NewPath = PathfindingService:CreatePath(PathfindingAgents)
NewPath:ComputeAsync(RootPart.Position, Destination)
if NewPath.Status == Enum.PathStatus.Success then
local Waypoints = NewPath:GetWaypoints()
for _, Waypoint in ipairs(Waypoints) do
if Waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid.Jump = true
end
--Just in case
NewPath.Blocked:Connect(function(blockedWaypointIdx)
print("The enemy's path is blocked. Recalculating.")
if Objective and Objective.PrimaryPart then
FollowPath(Objective.PrimaryPart.Position)
end
end)
Humanoid:MoveTo(Waypoint.Position)
local Timer = Humanoid.MoveToFinished:Wait(1)
if not Timer then
print("Path timed out. Recalculating.")
if Objective and Objective.PrimaryPart then
FollowPath(Objective.PrimaryPart.Position)
end
end
end
else
print("Path failed. Recalculating. Sorry.")
end
]]
end
local function FindNearestTarget()
local NearestTarget = nil
local PlayerList = Players:GetPlayers()
for _, Player in pairs(PlayerList) do
local Character = Player.Character or Player.CharacterAdded:Wait()
if Character and Character.PrimaryPart then
local Distance = (Character.PrimaryPart.Position - RootPart.Position).Magnitude
if Distance <= AggroRange then
NearestTarget = Character
else
NearestTarget = Objective
end
end
end
return NearestTarget
end
while task.wait(0.5) do
local Target = FindNearestTarget()
if Target and Target.PrimaryPart then
--//Checking distance to be safe.
local Distance = (Target.PrimaryPart.Position - RootPart.Position).Magnitude
if Distance <= AggroRange then
Objective = Target
elseif not Target and Distance >= AggroRange then
Objective = game.Workspace:FindFirstChild("Crystal")
end
else
print("Character's RootPart cannot be found.")
end
if Objective and Objective.PrimaryPart then
FollowPath(Objective.PrimaryPart.Position)
end
end
end
return PathfindingModule