Hello Developers!
I've made a simple AI which will run away from players using Pathfinding, the issue however that it does indeed work just it doesn't change directions when encountering different players for example, I'm chasing the AI and the AI is almost infront of another player but the AI doesn't try to move around the player rather it just simply rams said player
Script:
--//NPC\\-- local NPC = script.Parent local Humanoid = NPC.Humanoid --//Services\\-- local RunService = game:GetService("RunService") local Players = game:GetService("Players") local PathFindingService = game:GetService("PathfindingService") --//Functions\\-- local function RunAway() local Radius = 50 for _, Player in ipairs(Players:GetChildren()) do if Player:IsA("Player") then local Character = Player.Character local RootPart = Character:WaitForChild("HumanoidRootPart") if (RootPart.Position - NPC.HumanoidRootPart.Position).Magnitude < Radius then local NewPath = PathFindingService:CreatePath() NewPath:ComputeAsync(RootPart.Position, NPC.HumanoidRootPart.Position) 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 Humanoid:MoveTo(NPC.HumanoidRootPart.Position * Vector3.new(10,0,0)) Humanoid.MoveToFinished:Wait() end end end end end end --//Pathfinding\\-- RunService.Heartbeat:Connect(function() RunAway() end)
This is because even though you are looping through all players, only the path away from first player is calculated. Second and subsequent players will not be taken into account, until the humanoid reaches the end of the calculated path.
In practice it will never happen though, as You have connected Your function to the Heartbeat. So by the time the loop reaches second player, another Heartbeat recalculates everything. Heartbeat runs up to 60FPS!
So this script is essentially reverse zombie. As such, NPS must find the NEAREST player, and try to run away from it. To avoid grinding server resources to the ground, I suggest to re-check which player is closest about each second. Then you can adjust it to needs as needed.
Connecting to Heartbeat is an Overkill imho.
EDIT 2: It seems your pathfinding targets are wrong, and I do not know how did it work for you previously. For NPC to run away along the path, you have to choose a specific point on the map during the COMPUTE phase, rather than adjusting the path afterwards.
local currentFollowedRoot local function RunAway(RootPart) local NewPath = PathFindingService:CreatePath() NewPath:ComputeAsync(NPC.HumanoidRootPart.Position, NPC.HumanoidRootPart.Position * Vector3.new(10,0,0)) -- adjust the target here 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 Humanoid:MoveTo(Waypoint.Position) -- this needs to be a waypoint Humanoid.MoveToFinished:Wait() if currentFollowedRoot ~= RootPart then return -- break the path, as new player is found end end end end -- periodically find the nearest player task.spawn(function() while NPC.Parent do --break the loop when the NPC is destroyed local Radius = 50 local nearestRoot for _, plr in pairs(Players:GetPlayers()) do if plr.Character then local root = plr.Character:WaitForChild('HumanoidRootPart') local magnitude = (root.Position - NPC.HumanoidRootPart.Position).Magnitude if magnitude < Radius then Radius = magnitude nearestRoot = root end end end if nearestRoot then currentFollowedRoot = nearestRoot task.spawn(function() --edit: I forgor to run this in coroutine RunAway(nearestRoot) end) end task.wait(1) end end)
EDIT: Added coroutine for the RunAway function, to prevent it from pausing the loop.
EDIT 2: Fixed the pathfind.