当您致电 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 秒重新计算到最近玩家的路径。该路径存储为一系列航路点,并使用Humanoid.MoveToFinished signal 作为触发器移动到下一个已知航路点。每当重新计算路径时,我们只需重新开始该过程。
使用此系统,循环不会被阻塞,并且可以定期重新计算到不同玩家的距离和路径。这使得 NPC 也可以动态地将目标切换到最近的玩家。