Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

NPC runs away from players, but doesn't changes directions when a player is close to it (?)

Asked by 1 year ago

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)
0
I edited the answer (again). Hope this helps. sleazel 1287 — 1y

1 answer

Log in to vote
1
Answered by
sleazel 1287 Moderation Voter
1 year ago
Edited 1 year ago

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.

0
It works, the only issue however is that it doesn't use Pathfinding anymore (Basically, when running away from a player, it doesn't pathfind so if it encounters a wall it will just simply move through it) imnotaguest1121 362 — 1y
Ad

Answer this question