Hello, I have a pathfinding ai that works fine other than when it’s chasing a player and the player turns a corner and the ai loses sight, the ai turns around as if it’s patrolling again then instantly goes back into chasing the player, any help to smooth this out?
local Dummy = script.Parent
local Humanoid = Dummy.Humanoid
local IsPatrolling = true
Dummy.PrimaryPart:SetNetworkOwner(nil)
local Rand = Random.new()
local Waypoints = workspace.Area.Waypoints:GetChildren()
local RaycastLength = 70
local AutoDetectRadius = 20
local PlayersInSafeRoom = require(script.SafeRoomHandler)
local PathfindingService = game:GetService("PathfindingService")
local PathParams = {
["AgentHeight"] = 9,
["AgentRadius"] = 6,
["AgentCanJump"] = false
}
local LastTarget
local HasTarget = false
local LastSeen
local RaycastParam = RaycastParams.new()
RaycastParam.FilterDescendantsInstances = {Dummy}
RaycastParam.FilterType = Enum.RaycastFilterType.Blacklist
local function CanSeeTarget(Target)
local origin = Dummy.PrimaryPart.Position
local direction = (Target.PrimaryPart.Position - Dummy.PrimaryPart.Position)
-- If player is in not safe room
if not table.find(PlayersInSafeRoom, Target) then
-- Cast ray to check walls
local RaycastResult = workspace:Raycast(origin, direction + direction.Unit, RaycastParam)
if RaycastResult then
-- Hit something!
local Hit = RaycastResult.Instance
if Hit:IsDescendantOf(Target) then
-- No walls in between player and dummy, check if they're in front or near the player
if Dummy.PrimaryPart.CFrame.LookVector:Dot(direction) > 0 or direction.Magnitude < AutoDetectRadius then
-- Can see player!
return true
end
end
end
end
return false
end
local function FindTarget()
local Players = game:GetService("Players"):GetPlayers()
local MaxDistance = math.huge
local Nearest = nil
for _, Player in pairs(Players) do
local Character = Player.Character
if Character then
if Character.Humanoid.Health > 0 then
local Distance = (Dummy.PrimaryPart.Position - Character.PrimaryPart.Position).Magnitude
if Distance < MaxDistance and CanSeeTarget(Character) then
Nearest = Character
MaxDistance = Distance
end
end
end
end
if Nearest then
HasTarget = true
LastTarget = Nearest
LastSeen = os.time()
return Nearest
else
--Check if it has found a player before
if LastTarget then
if os.time() - LastSeen < 4 then
-- Hasn't been 4s
return LastTarget
end
end
LastTarget = nil
HasTarget = false
return nil
end
end
local function MoveTo(Destination, IsAttacking)
local Path = PathfindingService:CreatePath(PathParams)
Path:ComputeAsync(Dummy.PrimaryPart.Position, Destination.Position)
if Path.Status == Enum.PathStatus.Success then
for _, Waypoint in pairs(Path:GetWaypoints()) do
if HasTarget and not IsAttacking then
-- Stop when a target is found and only patrolling
return
end
-- Automatically break when he sees you again
if IsAttacking then
if CanSeeTarget(Destination.Parent) then
break
end
end
Humanoid:MoveTo(Waypoint.Position)
Humanoid.MoveToFinished:Wait()
end
end
end
local function Patrol()
if IsPatrolling then
local r = Rand:NextInteger(1, #Waypoints)
local Waypoint = Waypoints[r]
if not HasTarget then
MoveTo(Waypoint)
else
task.wait()
end
-- No need for infinite loops
Patrol()
end
end
local function Attack(Target)
local Distance = (Dummy.PrimaryPart.Position - Target.PrimaryPart.Position).Magnitude
if Distance > 2 then
if CanSeeTarget(Target) then
Humanoid:MoveTo(Target.PrimaryPart.Position)
else
MoveTo(Target.PrimaryPart, true)
-- Lose Target if he can't see you anymore
if not CanSeeTarget(Target) then
LastTarget = nil
end
end
else
Target.Humanoid.Health = 0
HasTarget = false
LastTarget = nil
end
end
local StartTargetting = coroutine.wrap(function()
while IsPatrolling do
local Target = FindTarget()
if Target then
Attack(Target)
end
task.wait()
end
end)
StartTargetting()
Patrol()