Tìm con đường là quá trình di chuyển một nhân vật trên một con đường hợp lý để đạt được một kết quả, tránh các rào chắn và (tùy chọn) vật liệu nguy hiểm hoặc khu vực định.
Tiết kiệm Navigation
Để hỗ trợ với việc tìm đường và đăng nhập, Studio có thể tạo một lưới điều hướng và nhãn modifier để bật chúng. Để bật chúng, bật Navigation Mesh và Pathfinding Modifiers từ trụ cột 2>Tùy chọn hiể
Với Bản đồ dẫn đường được bật, các khu vực màu được hiển thị nơi mà một nhân vật có thể đi bộ hoặc bơi, trong khi các khu vực màu không được bật. Các mũi tên nhỏ cho thấy các khu vực mà
Với Pathfinding modifiers được bật, nhãn văn bản cho thấy các vật liệu và khu vực cụ thể mà được xem xét khi sử dụng Pathfinding modifiers .
Giới hạn xác định
Các tính năng tìm con đường có những hạn chế cụ thể để đảm bảo hiệu suất xử lý hiệu lựcquả và tối ưu.
Giới hạn đặt hàng ngang
Tính toán Pathfinding chỉ xem xét các bộ phận trong một số giới hạn dọc nhất định:
- Giới hạn thấp hơn — Các bộ phận với một mặt Y coordenate thấp hơn -65,536 studs được bỏ qua.
- Phần cao hơn giới hạn - Parts với một trục Y lớn hơn 65,536 studs được bỏ qua.
- Span dọc — Khoảng cách dọc từ phần dưới cùng của thân hình Y đến đỉnh Y của thân hình phải không vượt quá 65.536 studs; nếu không, hệ thống tìm đường sẽ bỏ qua những bộ phận đó trong quá trình tìm đường.
Giới hạn khoảng cách tìm kiếm
Khoảng cách trực tiếp từ dòng này đến điểm kết thúc phải không vượt quá 3.000 studs. Vượt quá khoảng cách này sẽ kết thúc bằng trạng tháihiệu NoPath.
Tạo Con Đường
Tìm con đường được khởi tạo thông qua PathfindingService và chức năng Class.PathfindingService:CreatePath()|CreatePath() của nó.
Script địa phương
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() chấp nhận một bảng dữ liệu tùy chọn các tham số mà hành động nhân vật (đặc vụ) trên con đường.
Chìa khóa | Mô tả | Kiểu | Mặc định |
---|---|---|---|
AgentRadius | Bán kính đặc vụ, ở dấu chấm. Hữu ích để xác định mức tối thiểu cách xa của vật cản. | số | 2 |
AgentHeight | Chiều cao đặc vật, trong studs. Khoảng trống nhỏ hơn giá trị này, như khoảng trống dưới cầu thang, sẽ được xem như là không có thể di chuyển. | số | 5 |
AgentCanJump | Xác định có phép nhảy trong quá trình tìm con đường hay không. | boolean | true |
AgentCanClimb | Xác định xem có được phép leo trèo TrussParts trong quá trình tìm đường. | boolean | false |
WaypointSpacing | Khoảng cách giữa các điểm dừng trung gian trong con đường. Nếu được đặt để math.huge, sẽ không có điểm dừng trung gian. | con số | 4 |
Costs | Bảng vật liệu hoặc đã định PathfindingModifiers và chi phí cho vận chuyển. Hữu ích cho việc làm cho đặc tính agent yêu thích một số vật liệu/vùng khu vực hơn là những vùng khác. Xem modifiers để chi tiết. | bảng | nil |
Script địa phương
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
Ghi chú rằng đặt TrussParts để AgentCanClimb khi tạo một con đường khiến agen không thể leo trên con đường leo trên trụ cột khi không có gì cản
LocalScript - Con đường leo trèo
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- Chi phí của con đường leo; mặc định là 1}})
Di chuyển theo các hành trình
Phần này sử dụng script tìm đường dưới đây cho nhân vật của người chơi. Để kiểm tra trong khi đọc:
- Copy code into a LocalScript within StarterCharacterScripts .
- Chỉnh dòng 11 đến một Vector3 mục tiêu mà người nhân vật của người chơi có thể tiếp cận.
- Làm theo các mục tiếp theo để biết về việc tính toán con đường và di chuyển nhân vật.
LocalScript - Tìm con đường nhân vật
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- Tính đường đi
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Nhận đường dẫn
waypoints = path:GetWaypoints()
-- Xác định nếu con đường trở nên bị chặn
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Kiểm tra xem rào chắn đang ở dưới con đường nữa không
if blockedWaypointIndex >= nextWaypointIndex then
-- Ngưng dò đường đi cho đến khi đường đi được tính toán lại
blockedConnection:Disconnect()
-- Gọi chức năng để tính lại con đường mới
followPath(destination)
end
end)
-- Ngược khi di chuyển đến điểm dừng tiếp theo hoàn tất
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Tăng chỉ số điểm dừng và di chuyển đến điểm dừng tiếp theo
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Đầu tiên di chuyển đến điểm dừng thứ hai (điểm dừng đầu tiên là khởi bắt đầu; bỏ qua nó)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
Tính đường đi
Sau khi bạn đã tạo một con đường hợp lệ với CreatePath() , nó phải được tính toán bằng cách gọi Class.Path:ComputeAsync() với một Path:ComputeAsync() cho cả điểm xuất phát và điểm đến.
LocalScript - Tìm con đường nhân vật
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- Tính đường đi
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end
Đang nhận điểm dừng
Một khi Path được tính, nó sẽ chứa một loạt các điểm waypoint được theo dõi từ đầu đến kết thúc. Các điểm này có thể được thu thập với chức năng Path:GetWaypoints().
LocalScript - Tìm con đường nhân vật
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- Tính đường đi
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Nhận đường dẫn
waypoints = path:GetWaypoints()
end
end
Di chuyển con đường
Mỗi điểm dừng đều bao gồm cả một vị trí ( Vector3 ) và một h
LocalScript - Tìm con đường nhân vật
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- Tính đường đi
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Nhận đường dẫn
waypoints = path:GetWaypoints()
-- Xác định nếu con đường trở nên bị chặn
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Kiểm tra xem rào chắn đang ở dưới con đường nữa không
if blockedWaypointIndex >= nextWaypointIndex then
-- Ngưng dò đường đi cho đến khi đường đi được tính toán lại
blockedConnection:Disconnect()
-- Gọi chức năng để tính lại con đường mới
followPath(destination)
end
end)
-- Ngược khi di chuyển đến điểm dừng tiếp theo hoàn tất
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Tăng chỉ số điểm dừng và di chuyển đến điểm dừng tiếp theo
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Đầu tiên di chuyển đến điểm dừng thứ hai (điểm dừng đầu tiên là khởi bắt đầu; bỏ qua nó)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Xử lý các con đường bị chặn
Nhiều thế giới Roblox là dinamical; các bộ phận có thể di chuyển hoặc rơi và các sàn có thể sụp đổ. Điều này có thể chặn một con đường tính toán và ngăn chặn nhân vật đến đích của nó. Để xử lý điều này, bạn có thể kết nối sự kiện Path.Blocked
LocalScript - Tìm con đường nhân vật
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- Tính đường đi
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Nhận đường dẫn
waypoints = path:GetWaypoints()
-- Xác định nếu con đường trở nên bị chặn
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Kiểm tra xem rào chắn đang ở dưới con đường nữa không
if blockedWaypointIndex >= nextWaypointIndex then
-- Ngưng dò đường đi cho đến khi đường đi được tính toán lại
blockedConnection:Disconnect()
-- Gọi chức năng để tính lại con đường mới
followPath(destination)
end
end)
end
end
Hệ số nhân bản đường
Bởi mặc định, Path:ComputeAsync() trả về con đường ngắn nhất giữa điểm xuất phát và mục tiêu, với ngoại lệ là nó thử cản trở nhảy. Điều này có vẻ như một sự thiếu tự nhiên trong một số trường hợp - ví ví dụ / trường hợp
Để tối ưu hóa việc tìm con đường nữa, bạn có thể thực hiện modifiers pathfinding để tính toán những con đường thông minh qua các vật liệu khác nhau, xung quanh các vùng khu vực định, hoặc qua trở ngại .
Tùy chỉnh chi phí vật liệu
Khi làm việc với Terrain và BasePart材料, bạn có thể bao gồm một bảng Costs trong 1> Class.PathfindingService:CreatePath()|CreatePath()</
Các chìa khóa trong bảng Costs nên là tên chuỗi đại diện cho tên Enum.Material , ví dụ như Water cho 1> Nem.Material.Water1> .
LocalScript - Tìm con đường nhân vật
local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,Mud = 5,Neon = math.huge}})
Làm việc với các khu vực
Trong một số trường hợp, tùy chọn vật liệu không đủ. Ví dụ, bạn có thể muốn các nhân vật tránh một vùng định义 , bất kể vật liệu dưới chân. Điều này có thể được thực hiện bằng cách thêm một PathfindingModifier đối tượ
Tạo một phần Anchored xung quanh khu vực nguy hiểm và thiết lập thuộc tính CanCollide của nó thành false .
Lập một PathfindingModifier instance vào phần, tìm kiếm thuộc tính của nó, và giao một tên có ý nghĩa như Label .
Bao gồm một bảng Costs trong Class.PathfindingService:CreatePath()|CreatePath() có chứa một chìa khóa và giá trị số tương ứng. Một biến đổi có thể được định nghĩa là không có vị trí bằng cách thiết lập giá trị của nó thành Library.math.huge .
LocalScript - Tìm con đường nhân vậtlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {DangerZone = math.huge}})
Làm lơ các rào chắn
Trong một số trường hợp, có ích để điều tra qua các rào chắn vững chắc như thể chúng không tồn tại. Điều này cho phép bạn tính toán một con đường qua các rào chắn vật lý cụ thể, chứ không phải tính toán toàn bộ các rào chắn.
Tạo một phần Anchored xung quanh mục tiêu và thiết lập thuộc tính CanCollide của nó thành false .
Lập một PathfindingModifier instance lên phần và bật PassThrough 속성.
Bây giờ, khi một con đường được tính từ NPC zombie đến nhân vật người chơi, con đường tiếp tục xa hơn cửa và bạn có thể kêu gọi zombie vượt qua nó. Ngay cả khi zombie không thể mở cửa, nó vẫn phản ứng như thể nó "nghe" nhân vật đằng sau cửa.
Xây dựng liên kết
Đôi khi nó là cần thiết để tìm một con đường qua một không gian mà không thể đi qua bình thường, chẳng hạn như qua một hẻm núi, và thực hiện một hành động tùy chỉnh để đạt đến điểm dừng tiếp theo. Điều này có thể được thực hiện thông qua đố
Sử dụng ví dụ hòn đảo ở trên, bạn có thể khiến đặc vụ sử dụng một chiếc thuyền thay vì bước qua tất cả các cầu.
Để tạo một PathfindingLink bằng cách sử dụng ví dụ này:
Để giúp với việc hiển thị và trình diệt lỗi, bật Pathfinding links từ widget Tùy chọn hiển thị ở góc trên cùng bên phải của 3D viewport.
Tạo hai Attachments , một ở vị trí chỗ ngồi thuyền và một ở gần vị trí hạ cánh thuyền.
Tạo một PathfindingLink đối tượng trongWorkspace, sau đó gán Attachment0 và Attachment1 속性 cho các kết nối bắt đầu và kết thúc tương ứng.
Gán một cái tên có ý nghĩa như UseBoat cho định tính Label của nó. Tên này được sử dụng như một lá cờ trong script đường dẫn để kích hoạt một hành động tùy chỉnh khi agen đến điểm xuất phát.
Bao gồm một bảng Costs trong Class.PathfindingService:CreatePath()|CreatePath() có chứa cả một chìa khóa Water và một chìa khóa tùy chỉnh phù hợp với tên 1> Class.PathfindingLink.Label|Label1> của thuộc t
LocalScript - Tìm con đường nhân vậtlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})Trong sự kiện mà lỗ đến khi đạt được một điểm dừng, thêm một hành động tùy chỉnh cho tên modifier Label và thực hiện một hành động khác ngoài Humanoid:MoveTo() - trong trư
LocalScript - Tìm con đường nhân vậtlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})local player = Players.LocalPlayerlocal character = player.Characterlocal humanoid = character:WaitForChild("Humanoid")local TEST_DESTINATION = Vector3.new(228.9, 17.8, 292.5)local waypointslocal nextWaypointIndexlocal reachedConnectionlocal blockedConnectionlocal function followPath(destination)-- Tính đường đilocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- Nhận đường dẫnwaypoints = path:GetWaypoints()-- Xác định nếu con đường trở nên bị chặnblockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- Kiểm tra xem rào chắn đang ở dưới con đường nữa khôngif blockedWaypointIndex >= nextWaypointIndex then-- Ngưng dò đường đi cho đến khi đường đi được tính toán lạiblockedConnection:Disconnect()-- Gọi chức năng để tính lại con đường mớifollowPath(destination)endend)-- Ngược khi di chuyển đến điểm dừng tiếp theo hoàn tấtif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- Tăng chỉ số điểm dừng và di chuyển đến điểm dừng tiếp theonextWaypointIndex += 1-- Sử dụng thuyền nếu nhãn đường đi là "Sử dụng thuyền"; otherwise move to next waypointif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- Đầu tiên di chuyển đến điểm dừng thứ hai (điểm dừng đầu tiên là khởi bắt đầu; bỏ qua nó)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = workspace.BoatModelhumanoid.Seated:Connect(function()-- Bắt đầu di chuyển thuyền nếu đặt người láiif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- Xác định vị trí hạn chế trong mối quan hệ với hòn đảolocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- Dừng thuyền khi ở gần hòn đảoif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- Làm giả đại lý và tiếp tục đến đíchhumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
Tương thích phát sóng
In-experience instreamming là một tính năng mạnh mẽ tải và tải lại 3D nội dung như một người chơivật nhảy quanh thế giới. Khi họ khám phá không gian 3D, các subset mới của không gian stream đến thiết bị của họ và một số subset cũ có thể stream ra.
Xem xét các mô tả tốt nhất sau đây cho việc sử dụng PathfindingService trong các trải nghiệm kích hoạt streaming:
Phát sóng có thể chặn hoặc mở khóa một con đường nhất định khi một nhân vật di chuyển theo nó. Ví dụ, khi một nhân vật chạy qua một rừng, một cây có thể chảy vào một nơi ở phía trước họ và làm cản trở con đường. Để làm cho phát sóng
Một phương pháp phổ biến trong tìm con đường là sử dụng các biến cố của các đối tượng hiện có để tạo một <
Để đối phó với vấn đề này, xem xét đặt mục tiêu đến vị trí của một BasePart trong một mô hình thường xuyên dưới đây. Các mô hình thường xuyên mở sau khi người chơi tham gia và ch