探路者让我的 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 动态地将目标切换到最近的玩家。
我正在尝试制作 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 动态地将目标切换到最近的玩家。