- What do you want to achieve? Keep it simple and clear!
I’m trying to create a pathfinding AI that is able to maintain a certain distance from the player and back away whilst facing the player when approached
- What is the issue? Include screenshots / videos if possible!
When I implement the stare function, the AI movement functions are delayed; instead of backing away smoothly, the AI will periodically stop moving before resuming their movement. Furthermore, the AI pathfinding will become very delayed, taking as long as a second to begin moving toward the player. Both of these issues are resolved when the stare function is disabled.
Video of the issue below
- What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried a few different scripts to rotate the part, all using cframes, I’ve tried to set the network owner of the AI to the server, and I’ve tried running the stare function as a separate script from the rest of the move functions using _G.
Here is the current script I’m using
local Stalker = script.Parent
local RootPart = Stalker.HumanoidRootPart
local PathfindingService = game:GetService("PathfindingService")
local TweenService = game:GetService("TweenService")
for i, v in pairs(Stalker:GetDescendants())do
if v:IsA("BasePart")then
v:SetNetworkOwner(nil)
end
end
--The stalker has the following behavior:
--1) Identify nearest player as the "Target"
--2) If distance from target is greater than 40, follow them until in range
--3) If distance from target is less than 30, walk backwards until in range
--4) If the target is in view and within 100 studs, face them
local function findTarget() --Identifies the closest player and labels them as a target
local players = game.Players:GetPlayers()
local maxDistance = 100
local nearestTarget = nil
for index, player in pairs(players) do
if player.Character then
local target = player.Character
local distance = (target.HumanoidRootPart.Position - RootPart.Position).magnitude
if distance < maxDistance then
nearestTarget = target
maxDistance = distance
end
end
return nearestTarget
end
end
local function stare() --npc faces target
local rotateCFrame = CFrame.lookAt(Stalker.HumanoidRootPart.Position, Vector3.new(findTarget().Head.Position.X, Stalker.HumanoidRootPart.Position.Y, findTarget().Head.Position.Z))
local rotateTweenInfo = TweenInfo.new()
local tween = TweenService:Create(Stalker.HumanoidRootPart, rotateTweenInfo, {CFrame = rotateCFrame})
tween:Play()
end
local function canSeeTarget() -- detects whether or not there's a line of sight between the target and the stalker
local origin = RootPart.Position
local destinationDir = (findTarget().HumanoidRootPart.Position - RootPart.Position).unit * 100
local ray = Ray.new(origin, destinationDir)
local hit, pos = workspace:FindPartOnRay(ray, Stalker)
if hit then
if hit:IsDescendantOf(findTarget()) then
return true
else
return false
end
end
end
local function getPath() -- creates a path to the target
local pathParams = {
["AgentRadius"] = 3,
["AgentCanJump"] = false,
["WaypointSpacing"] = 1
}
local path = PathfindingService:CreatePath(pathParams)
path:ComputeAsync(RootPart.Position, findTarget().HumanoidRootPart.Position)
return path
end
local function stalkTarget() -- maintain 35 +-5 dist. from target
local path = getPath()
local distance = (findTarget().HumanoidRootPart.Position - RootPart.Position).magnitude
local direction = (findTarget().HumanoidRootPart.Position - RootPart.Position).unit
for index, waypoint in pairs(path:GetWaypoints()) do
local distance = (findTarget().HumanoidRootPart.Position - RootPart.Position).magnitude
local direction = (findTarget().HumanoidRootPart.Position - RootPart.Position).unit
if distance > 40 or canSeeTarget() == false then --chase
Stalker.Humanoid.AutoRotate = true
Stalker.Humanoid:MoveTo(waypoint.Position)
Stalker.Humanoid.MoveToFinished:Wait()
elseif distance < 100 and canSeeTarget() == true then --stare
Stalker.Humanoid.AutoRotate = false
stare()
if distance < 30 then -- evade
Stalker.Humanoid:MoveTo(RootPart.Position + direction * -10)
Stalker.Humanoid.MoveToFinished:Wait()
end
else --idle
Stalker.Humanoid.AutoRotate = true
end
end
end
while task.wait() do -- activate AI when target is within range
findTarget()
if findTarget() then
stalkTarget()
end
end