探路者让我的 NPC 只跟随我最老的位置

Pathfinder is making my NPC follow my oldest position only

我正在尝试制作 maze/horror 游戏。我使用 Roblox 库中的在线模板作为我的敌人。正如您将在下面的代码中看到的那样,我使用了探路者。它像它应该的那样找到我,除了它只适用于我的最后一个位置。正如你在下图中看到的,它完全跳过了我,走到了我的最后一个位置,然后开始追我。我不知道为什么它只适用于我的最后一个职位,而不适用于我现在的职位。

local PathFindingS = game:GetService("PathfindingService")
local humanoid = script.Parent:WaitForChild("Humanoid")
local rootPart = script.Parent:WaitForChild("HumanoidRootPart")
local Players = game:GetService("Players")
game.Workspace.Fruity.Humanoid.WalkSpeed = 60       


--To calculate the path
while wait() do
    
    for i, player in pairs(game.Players:GetPlayers()) do
        local character = game.Workspace:WaitForChild(player.Name)
        local characterPos = character.PrimaryPart.Position
        local path = PathFindingS:CreatePath()
        path:ComputeAsync(rootPart.Position, characterPos)
        game.Workspace.Fruity.HumanoidRootPart:SetNetworkOwner(nil) 
        
        local waypoints = path:GetWaypoints()

        for i, waypoint in pairs(waypoints) do
            local part = Instance.new("Part")
            part.Shape = "Ball"
            part.Material = "Neon"
            part.Size = Vector3.new(0.6,0.6,0.6)
            part.Position = waypoint.Position + Vector3.new(0,2,0)
            part.Anchored = true
            part.CanCollide = false
            part.Parent = game.Workspace
            humanoid:MoveTo(waypoint.Position)
            humanoid.MoveToFinished:Wait()  
        end 
    end
end

当您调用 path:ComputeAsync(rootPart.Position, characterPos) 时,您的 NPC 的寻路会更新。它没有更频繁地更新的原因是你用最后一行阻止了下一个循环的开始:humanoid.MoveToFinished:Wait()

您的代码告诉 NPC,它必须走到每个玩家之间的每个点,一次可能需要几分钟,然后才能再次计算路径。

解决这个问题的方法是让它能够快速和异步地重新计算路径。为此,请尝试这样的操作:

local PathfindingService = game:GetService("PathfindingService")
local PlayerService = game:GetService("Players") 
local humanoid = script.Parent:WaitForChild("Humanoid")
local rootPart = script.Parent:WaitForChild("HumanoidRootPart")


-- create a place where pathfinding orbs can be created and destroyed quickly
local shouldDebugPath = true
local OrbFolder = Instance.new("Folder", game.Workspace)
OrbFolder.Name = "Debug - Orbs"
local OrbTemplate = Instance.new("Part")
OrbTemplate.Shape = Enum.PartType.Ball
OrbTemplate.Material = Enum.Material.Neon
OrbTemplate.Size = Vector3.new(0.6,0.6,0.6)
OrbTemplate.Anchored = true
OrbTemplate.CanCollide = false
local function createWaypoint(position)
    local orb = OrbTemplate:Clone()
    orb.Position = position + Vector3.new(0,2,0)
    orb.Parent = OrbFolder
    
    return orb
end


-- set up some navigation variables and set up a chain
-- so that when the humanoid arrives at a waypoint,
-- it automatically selects the next point.
local currentOrbIndex = 0
local currentPath = {} -- store pathfinding waypoints here 
local function moveToNextWaypoint(previousPointReached) 
    currentOrbIndex += 1
    if currentOrbIndex > #currentPath then
        return
    end
    
    local nextWaypoint = currentPath[currentOrbIndex]
    humanoid:MoveTo(nextWaypoint.Position)
end
humanoid.MoveToFinished:Connect(moveToNextWaypoint)


-- calculate and continually update the path
local pauseLength = 1.0 --seconds (lower this number to speed up refresh rate)
while wait(pauseLength) do
    
    -- find the closest player's character model
    local targetCharacter = nil
    local closestDist = math.huge
    local playerList = PlayerService:GetPlayers()
    for i, player in pairs(playerList) do
        -- check that the player's character has spawned in
        local character = player.Character
        if not character then
            continue
        end
        
        -- do some quick maths and select which player is closest
        local p1 = character.PrimaryPart.Position
        local p2 = rootPart.Position
        local d = math.abs((p1 - p2).Magnitude)
        if d < closestDist then
            closestDist = d
            targetCharacter = character
        end
    end
    
    -- check that there are actually players in the server
    if targetCharacter == nil then
        continue
    end
        
    -- compute the path to the character
    local characterPos = targetCharacter.PrimaryPart.Position
    local path = PathfindingService:CreatePath()
    path:ComputeAsync(rootPart.Position, characterPos)
    local waypoints = path:GetWaypoints()
    
    -- debug : show the path to the player
    if shouldDebugPath then
        OrbFolder:ClearAllChildren()    
        for i, waypoint in pairs(waypoints) do
            local position = waypoint.Position
            createWaypoint(position)
        end
    end
    
    -- start the player walking towards the nearest player
    currentOrbIndex = 0
    currentPath = waypoints
    moveToNextWaypoint()
end

此解决方案每 1 秒重新计算一次到最近玩家的路径。该路径存储为一系列 waypoints 并使用 Humanoid.MoveToFinished signal 作为移动到下一个已知航路点的触发器。每当重新计算路径时,我们只需重新开始该过程。

有了这个系统,环路就不会被阻塞,并且可以定期重新计算到不同玩家的距离和路径。这也允许 NPC 动态地将目标切换到最近的玩家。