การหาเส้นทาง เป็นกระบวนการย้ายตัวละครของคุณตามเส้นทางที่เหมาะสมเพื่อให้ไปถึงจุดหมาย โดยหลีกเลี่ยงอุปสรรคและวัสดุอันตรางหรือภาพนำทางที่กำหนด
การเรียบเรียงการนำทาง
เพื่อช่วยให้การจัดเลี้ยงเส้นทางและการดีบั๊ก, Studio สามารถเรนเดอร์เมชการนำทางและ modifier เข็มชื่อ เพื่อเปิดใช้งานพวกเขา, เปิด เมชการนำทาง
มี เน็ตเวิร์กชุดนำทาง เปิดใช้งานแล้ว พื้นที่สีมีสีสันจะแสดงว่าตัวละครอาจเดินหรือว่ายน้ำได้ ในขณะที่พื้นที่ที่ไม่มีสีจะถูกบล็อก เล็ก��
ด้วย ตัวช่วยเหลือในการเลือกเส้นทาง เปิดใช้งานแล้ว ชื่อเรื่องข้อความแสดงถึงวัสดุและภูมิภาคที่เป็นไปตามเมื่อใช้ ตัวช่วยเหลือในการเลือกเส้นทาง
ข้อจำกัดที่ทราบ
การดำเนินการ
ขีดจำกัดการวางแนวตั้ง
การคำนวณเส้นทางพิจารณาเฉพาะชิ้นส่วนภายในขอบเขตตั้งฉงกิจของบางส่วนเท่านั้น:
- ต่ำกว่าขีดจำกัด — ชิ้นส่วนที่มี coordinated Y ด้านล่างไม่ได้รับการรองรับ Lower Boundary — ชิ้นส่วนที่มี coordinated Y ด้านล่างไม่ได้รับการรองรับ
- อัปเปอร์ขีดจำกัด — ชิ้นส่วนที่มี top Y ความสูงเกิน 65,536 สตัดจะได้รับการเพิกเฉย
- ความได้รับการเรียกร้องแนวตั้ง — ความได้รับการเรียกร้องแนวตั้งจากด้านล่างของส่วนที่ต่ำที่สุด Y จะต้องจากส่วนที่สูงที่สุด Y จะต้องไม่เกิน 65,536 สตั๊ด
ค้นหาระยะทางจํากัด
ระยะทางตรงจากตรงไปยังเส้นทางที่ไม่เกิน 3,000 สตุ๊ด หากเกินระยะนี้จะทำให้เกิดสถานะ NoPath
การสร้างเส้นทาง
การหาเส้นทางเริ่มต้นขึ้นผ่าน PathfindingService และการใช้งาน CreatePath() ของมัน
สคริปต์ท้องถิ่น
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() รองรับตารางพารามิเตอร์ที่เป็นไปได้ซึ่งปรับแต่งวิธีที่ตัวละคร (เอเจนต์) เคลื่อนทางตามเส้นทาง
กุญแจ | คำอธิบาย | ชนิด | เริ่มต้น |
---|---|---|---|
AgentRadius | รัศมีเอเจนต์ ใน studs มีประโยชน์สำหรับการกำหนดความแยกที่ต่ำสุดจากอุปสรรค | ตัวเลข | 2 |
AgentHeight | ความสูงเอเจนต์ ในสตั๊ด พื้นที่ว่างเล็กกว่าค่านี้ เช่น พื้นที่ภายใต้บันไดจะถูกเครื่องหมายว่าไม่สามารถข้ามได้ | ตัวเลข | 5 |
AgentCanJump | กำหนดว่าคุณสามารถกระโดดในระหว่างการหาเส้นทางได้หรือไม่ | บูลีน | true |
AgentCanClimb | กำหนดว่าคุณสามารถ TrussParts ในระหว่างการหาเส้นทางได้หรือไม่ | บูลีน | false |
WaypointSpacing | การวางอันตรากตรงกลางจุดสิ้นสุดในเส้นทาง หากตั้งค่าไว้ที่ math.huge จะไม่มีจุดสิ้นสุดอันตรากตรงกลาง | จํานวน | 4 |
Costs | ตารางวัสดุหรือ PathfindingModifiers และค่าใช้จ่ายสําหรับการเดินทาง มีประโยชน์สําหรับการทําให้เอเจนต์ชื่นชอบวัสดุ/ภูมิภาคบางอย่างมากกว่าคนอื่น ดู โมดิฟิเกอร์ | ตาราง | nil |
สคริปต์ท้องถิ่น
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
หมายเหตุว่าตัวแทนสามารถปีน TrussParts ในระหว่างการค้นหาเส้นทางโดยการตั้ง AgentCanClimb เป็น true
LocalScript - เส้นทางปีนเขา
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- ค่าใช้จ่ายสำหรับเส้นทางปีนเขา; ค่าเริ่มต้นคือ 1}})
ย้ายตามเส้นทาง
ส่วนนี้ใช้สคริปต์เพิ่มเส้นทางต่อไปนี้สำหรับตัวละครของผู้เล่น เพื่อทดสอบในขณะที่อ่าน:
- คัดลอกโค้ดใน LocalScript ภายใน StarterCharacterScripts
- แก้ไขบรรทัดที่ 11 เป็นจุดหมายปลายทาง Vector3 ที่ตัวละครของผู้เล่นสามารถถึง
- ดำเนินการต่อผ่านส่วนต่อไปเพื่อเรียนรู้เกี่ยวกับการคำนวณเส้นทางและการเคลื่อนที่ของตัวละคร
LocalScript - การหาเส้นทางตัวละคร
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)
-- คํานวณเส้นทาง
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- รับเส้นทางวิชา
waypoints = path:GetWaypoints()
-- ตรวจสอบว่าเส้นทางปกปิด
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- ตรวจสอบว่าอุปสรรคอยู่ด้านล่างเส้นทาง
if blockedWaypointIndex >= nextWaypointIndex then
-- หยุดตรวจสอบความสัมพันธ์ของเส้นทางจนกว่าเส้นทางจะถูกคำนวณใหม่
blockedConnection:Disconnect()
-- โทรหาฟังก์ชันเพื่อคํานวณเส้นทางใหม่
followPath(destination)
end
end)
-- ตรวจสอบเมื่อการเคลื่อนไหวไปยังจุดหมายต่อไปเสร็จสิ้น
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- เพิ่มดัชนี Waypoint และย้ายไปยัง Waypoint ต่อไป
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- เคลื่อนย้ายไปยังจุดมุ่งหมายที่สอง (จุดเริ่มต้นเป็นเส้นทาง; ข้ามมัน)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
คํานวณเส้นทาง
หลังจากที่คุณสร้างเส้นทางที่ถูกต้องด้วย CreatePath() ต้องมีการคำนวณ โดยการเรียก Class.Path:ComputeAsync() ด้วย 1> Datatype.Vector31> สำหรับทั้งจุดเริ่
LocalScript - การหาเส้นทางตัวละคร
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)
-- คํานวณเส้นทาง
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end
รับ Waypoints
เมื่อ Path ถูกคำนวณจะประกอบด้วย วิธีการจุด ปิดจุดเหล่านี้สามารถรวบรวมได้ด้วย Path:GetWaypoints() ฟังก์ชัน
LocalScript - การหาเส้นทางตัวละคร
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)
-- คํานวณเส้นทาง
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- รับเส้นทางวิชา
waypoints = path:GetWaypoints()
end
end
การเคลื่อนทางเส้นทาง
แต่ละค่ายูงที่ประกอบด้วย ตําแหน่ง ( Vector3 ) และ ก
LocalScript - การหาเส้นทางตัวละคร
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)
-- คํานวณเส้นทาง
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- รับเส้นทางวิชา
waypoints = path:GetWaypoints()
-- ตรวจสอบว่าเส้นทางปกปิด
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- ตรวจสอบว่าอุปสรรคอยู่ด้านล่างเส้นทาง
if blockedWaypointIndex >= nextWaypointIndex then
-- หยุดตรวจสอบความสัมพันธ์ของเส้นทางจนกว่าเส้นทางจะถูกคำนวณใหม่
blockedConnection:Disconnect()
-- โทรหาฟังก์ชันเพื่อคํานวณเส้นทางใหม่
followPath(destination)
end
end)
-- ตรวจสอบเมื่อการเคลื่อนไหวไปยังจุดหมายต่อไปเสร็จสิ้น
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- เพิ่มดัชนี Waypoint และย้ายไปยัง Waypoint ต่อไป
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- เคลื่อนย้ายไปยังจุดมุ่งหมายที่สอง (จุดเริ่มต้นเป็นเส้นทาง; ข้ามมัน)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
การจัดการบล็อกโปรด
โลก Roblox จำนวนมากเป็นไดนามิก; ชิ้นส่วนอาจเคลื่อนที่หรือตกลงได้ และพื้นอาจล่มสลาย นี่คือการบล็อกเส้นทางที่คำนวณและป้องกันตัวละครจากการไปยังจุดหมาย เพื่อจัดการกับสิ่ง
LocalScript - การหาเส้นทางตัวละคร
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)
-- คํานวณเส้นทาง
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- รับเส้นทางวิชา
waypoints = path:GetWaypoints()
-- ตรวจสอบว่าเส้นทางปกปิด
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- ตรวจสอบว่าอุปสรรคอยู่ด้านล่างเส้นทาง
if blockedWaypointIndex >= nextWaypointIndex then
-- หยุดตรวจสอบความสัมพันธ์ของเส้นทางจนกว่าเส้นทางจะถูกคำนวณใหม่
blockedConnection:Disconnect()
-- โทรหาฟังก์ชันเพื่อคํานวณเส้นทางใหม่
followPath(destination)
end
end)
end
end
ตัวช่วยการหาเส้นทาง
โดยปกติ, Path:ComputeAsync() กลับค่าน้อยที่สุด เส้นทางสั้นที่สุด ระหว่างจุดเริ่มต้นและจุดหมาย, ยกเว้นว่ามันพยายามที่จะหลีกเลี่ยงการกระโดด นี่ดูผิด
เพื่อปรับปรุงการค้นหาเส้นทางอย่างต่อเนื่องคุณสามารถใช้ ตัวช่วยปรับปรุงเส้นทาง เพื่อคํานวณเส้นทางที่ฉลาดขึ้นได้ทั่ววัสดุต่างๆ รอบ ๆ ภายใน ภูมิภาค หรื
การตั้งค่าค่าวัสดุ
เมื่อทำงานกับ Terrain และ BasePart วัสดุคุณสามารถรวม Costs ตารางภายใน 1> Class.Pathfinding
รหัสในตาราง Costs ควรเป็นชื่อสตริงที่แทนที่ด้วยชื่อ Enum.Material โดยเฉพาะสำหรับชื่อ Water สำหรับ 1> Nem.Material.Water1>
LocalScript - การหาเส้นทางตัวละคร
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}})
ทำงานร่วมกับภูมิภาค
ในบางกรณี ความชอบวัสดุ ไม่เพียงพอ เช่น คุณอาจต้องการให้ตัวละครหลีกเลี่ยง ภายใต้สภาพแวดล้อมที่กำหนด ไม่ว่าวัสดุจะอยู่ด้านล่างหรือไม่ สิ่งนี้สามารถดำเ
สร้างส่วน Anchored รอบพื้นที่อันตรายและตั้งค่าสมบัติสมบัติ CanCollide ของมันเป็น ปิด
ใส่ตัวอย่าง PathfindingModifier ลงในชิ้นส่วน ค้นหาสมบัติของมัน และกำหนดชื่อที่มีความหมายเช่น Label
รวม Costs ตารางใน CreatePath() ที่มีคีย์ที่ตรงกันและมีค่าตัวเลขที่เกี่ยวข้อง ตัวแก้ไขสามารถกำหนดได้ว่าเป็นไม่เดินทางโดยการตั้งค่ามูลค่าข
LocalScript - การหาเส้นทางตัวละครlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {DangerZone = math.huge}})
การเพิกเฉยอุปสรรค
ในบางกรณี อาจเป็นประโยชน์ในการผสานผ่านสิ่งกีดขวางที่แข็งแกร่งโดยที่พวกเขาไม่มีอยู่จริง นี่ช่วยให้คุณคำนวณเส้นทางผ่านบล็อกทางกายภาพที่เฉพาะเจาะจงโดยไม่ต้องสูญเสียการคำนวณ
สร้างส่วน Anchored รอบวัตถุและตั้งค่าสมบัติสมบัติ CanCollide ของมันเป็น ฟลัง
ใส่ PathfindingModifier ตัวอย่างลงในชิ้นส่วนและเปิดสมบัติสมบัติ PassThrough ของมัน
ตอนนี้เมื่อเส้นทางถูกคำนวณจากซอมบี้ NPC ไปยังตัวละครผู้เล่น เส้นทางขยายออกไปนอกประตูและคุณสามารถเรียกร้องให้ซอมบี้ข้ามได้ แม้ว่าซอมบี้จะไม่สามารถเปิดประตูได้
ลิงค์ที่นำทางเส้นทาง
ในบางครั้งอาจจำเป็นต้องค้นหาเส้นทางข้ามพื้นที่ที่ไม่สามารถเดินทางได้ตามปกติ, เช่น ข้ามหุบเขา, และประกอบด้วยการกระทําที่กําหนดเองเพื่อให้ได้จุดหมายปลายทางต่อไป
โดยใช้ตัวอย่างเกาะด้านบนคุณสามารถให้เอเจนต์ใช้เรือแทนที่จะเดินข้ามสะพานทั้งหมด
เพื่อสร้าง Class.PathfindingLink โดยใช้ตัวอย่างนี้:
เพื่อช่วยให้มองเห็นและดีบั๊ก, เปิดใช้งาน ลิงค์การนำทาง จาก Visualization Options วิดเจ็ตในมุมมองด้านบนขวา
สร้างสอง Attachments บนที่นั่งของเรือและหนึ่งใกล้ที่น่าเทียบเรือ
สร้าง PathfindingLink วัตถุในพื้นที่ทํางาน, จากนั้นกําหนดคุณสมบัติของมัน แนบมา0 และ แนบมา1 ให้กับอุปกรณ์เริ่มต้นและสิ้นสุดตามลำดับ
กำหนดชื่อที่มีความหมายเช่น ใช้เรือ สมบัติสมุดของมัน ชื่อนี้ใช้เป็นธงในสคริปต์เส้นทางเพื่อเรียกใช้การกระทําที่กําหนดเมื่อเอเจนต์ไปยังจุดเริ่มต้นของลิงค์
รวม Costs ตารางภายใน CreatePath() ที่มีทั้ง Water กุญแจและรหัสที่ตรงกันสำหรับชื่อโปรไฟล์ 1> Class.PathfindingLink.Label|Label1>
LocalScript - การหาเส้นทางตัวละครlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})ในเหตุการณ์ที่เกิดขึ้นเมื่อมีคลาสเพิ่มตัวเรือและชื่อผู้ปรับแต่งคลาส Label และดำเนินการต่างๆ จาก Humanoid:MoveTo() ในก
LocalScript - การหาเส้นทางตัวละครlocal 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)-- คํานวณเส้นทางlocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- รับเส้นทางวิชาwaypoints = path:GetWaypoints()-- ตรวจสอบว่าเส้นทางปกปิดblockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- ตรวจสอบว่าอุปสรรคอยู่ด้านล่างเส้นทางif blockedWaypointIndex >= nextWaypointIndex then-- หยุดตรวจสอบความสัมพันธ์ของเส้นทางจนกว่าเส้นทางจะถูกคำนวณใหม่blockedConnection:Disconnect()-- โทรหาฟังก์ชันเพื่อคํานวณเส้นทางใหม่followPath(destination)endend)-- ตรวจสอบเมื่อการเคลื่อนไหวไปยังจุดหมายต่อไปเสร็จสิ้นif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- เพิ่มดัชนี Waypoint และย้ายไปยัง Waypoint ต่อไปnextWaypointIndex += 1-- ใช้เรือถ้าป้ายวิธีการใช้เรือเป็น "UseBoat"; ย้ายไปยังเรือถัดไปif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- เคลื่อนย้ายไปยังจุดมุ่งหมายที่สอง (จุดเริ่มต้นเป็นเส้นทาง; ข้ามมัน)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = workspace.BoatModelhumanoid.Seated:Connect(function()-- เริ่มเครื่องยนต์หากตัวแทนนั่งif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- ตรวจสอบตำแหน่งข้อจํากัดในความสัมพันธ์กับเกาะlocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- หยุดเรือเมื่ออยู่ใกล้เกาะif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- เอาตัวแทนออกและไปยังจุดหมายปลายทางhumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
ความเข้ากันได้กับสตรีมมิ่ง
ในประสบการณ์ การสตรีมอินสแตนซ์ เป็นคุณสมบัติที่มีประสิทธิภาพซึ่งโหลดและไม่โหลดเนื้อหา 3D ในขณะที่ตัวละครของผู้เล่นเคลื่อนไหวไปทั่วโลก เมื่อพวกเขาสำรวจพื้นท
พิจารณาวิธีการต่อไปนี้สำหรับการใช้ PathfindingService ในประสบการณ์ที่เปิดใช้งานการสตรีมมิ่ง:
การสตรีมสามารถบล็อกหรือปลดบล็อกเส้นทางที่กำหนดไว้เป็นตัวละครเคลื่อนทางผ่านมัน ตัวอย่างเช่น ในขณะที่ตัวละครวิ่งผ่านป่า ต้นไม้อาจสตรีมในที่ใดที่หน
การใช้วิธีการแก้ปัญหาทั่วไปในการค้นหาเส้นทางคือการใช้ตำแหน่งของวัตถุที่
เพื่อแก้ปัญหานี้ ลองตั้งเป้าหมายให้อยู่ในตำแหน่งของ BasePart ภายในแบบจดหมายของ Class.Workspace.PersistentLoaded|PersistentLoaded เมื่อผู้เล่นเข้าร่วมและพวกเขาจะ