การค้นหาเส้นทางตัวอักษร

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

การค้นหาเส้นทาง เป็นกระบวนการย้ายตัวละครไปตามเส้นทางโลจิสติกที่จะไปถึงจุดหมายโดยหลีกเลี่ยงอุปสรรคและ (ตัวเลือก) วัสดุอันตรายหรือพื้นที่ที่กำหนด

การแสดงภาพการนําทาง

เพื่อช่วยในการค้นหาเส้นทางและการดีบัก Studio สามารถเรนเดอร์เมชและแท็บปรับแต่ง modifierเพื่อเปิดใช้งานพวกเขาให้สลับเปิด เนวิเกชันเมช และ ตัวปรับเส้นทาง จากแท็บ ตัวเลือกการแสดงผล ในมุมขวาบนของหน้าต่าง 3D วิวพอร์ต

A close up view of the 3D viewport with the Visualization Options button indicated in the upper-right corner.

เมื่อเปิดใช้งานเมช เครือข่ายการนําทาง แล้ว พื้นที่สีสันจะแสดงตำแหน่งที่ตัวละครอาจเดินหรือว่ายน้ำ ในขณะที่พื้นที่สีไม่สันจะถูกบล็อกลูกศรขนาดเล็กบ่งบอกถึงพื้นที่ที่ตัวละครจะพยายามไปถึงโดยการกระโดดโดยสมมติว่าคุณตั้ง AgentCanJump เป็น true เมื่อ สร้างเส้นทาง

Navigation mesh showing in Studio

เมื่อเปิดใช้งานตัวปรับเปลี่ยนการค้นหาเส้นทาง **** แล้ว ฉลากข้อความจะระบุวัสดุและภูมิภาคที่เฉพาะเจาะจงที่จะนำมาพิจารณาเมื่อใช้ตัวปรับเปลี่ยนการค้นหาเส้นทาง

Navigation labels showing on navigation mesh

ข้อจำกัดที่รู้จัก

คุณลักษณะการค้นหาเส้นทางมีข้อจํากัดเฉพาะเพื่อให้แน่ใจว่ามีการประมวลผลอย่างมีประสิทธิภาพและประสิทธิภาพสูงสุด

ขีดจํากัดการวางแนวตั้ง

การคำนวณการค้นหาเส้นทางพิจารณาเฉพาะส่วนภายในขอบเขตแนวตั้งที่กำหนดเท่านั้น:

  • ขอบล่าง — ชิ้นส่วนที่มีพิกัดด้านล่าง Y น้อยกว่า -65,536 สตัดถูกมองข้าม
  • ขอบบน — ชิ้นส่วนที่มีพิกัดด้านบน Y เกิน 65,536 สตัดถูกเพิกเฉย
  • ช่วงแนวตั้ง — ระยะทางแนวตั้งจากด้านล่างส่วนที่ต่ำที่สุด Y ไปยังด้านบนส่วนที่สูงที่สุด Y ต้องไม่เกิน 65,536 สตัด; มิฉะนั้นระบบค้นหาเส้นทางจะไม่สนใจส่วนเหล่านั้นในระหว่างการคำนวณการค้นหาเส้นทาง

ข้อจํากัดระยะการค้นหา

ระยะการมองเห็นโดยตรงจากจุดเริ่มต้นถึงจุดสิ้นสุดไม่ควรเกิน 3,000 สตัด ที่การเกินระยะนี้จะส่งผลให้เกิดสถานะ NoPath

สร้างเส้นทาง

การค้นหาเส้นทางเริ่มต้นผ่าน PathfindingService และฟังก์ชัน CreatePath() ของมัน

สคริปท์ท้องถิ่น

local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath()

CreatePath() ยอมรับตารางพารามิเตอร์ที่เลือกได้ซึ่งปรับแต่งวิธีที่ตัวละคร (ตัวแทน) เคลื่อนที่ไปตามเส้นทาง

กุญแจคําอธิบายประเภทค่าเริ่มต้น
AgentRadiusรัศมีตัวแทน, ในสตัด มีประโยชน์สำหรับการกำหนดระยะการแยกขั้นต่ำจากอุปสรรคจํานวนเต็ม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 เมื่อ สร้างเส้นทาง และไม่มีอะไรบล็อกตัวแทนจากเส้นทางการปีนของเทรลล์เส้นทางที่ปีนได้มีป้าย ปีน และ ค่าใช้จ่าย สำหรับเส้นทางที่ปีนได้คือ 1 โดยปกติ

Path going up a climbable TrussPart ladder
สคริปท้องถิ่น - เส้นทางปีนเขาแทรส

local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath({
AgentCanClimb = true,
Costs = {
Climb = 2 -- ค่าของเส้นทางการปีน; ค่าเริ่มต้นคือ 1
}
})

เคลื่อนทางไปตามเส้นทาง

ส่วนนี้ใช้สคริปต์ค้นหาเส้นทางต่อไปนี้สำหรับตัวละครของผู้เล่น เพื่อทดสอบขณะอ่าน:

  1. คัดลอกโค้ดลงใน LocalScript ภายใน StarterCharacterScripts
  2. ตั้งแปร ให้เป็นจุดหมายปลายทางในโลก 3D ที่ผู้เล่นตัวละครสามารถเข้าถึงได้
  3. ดำเนินการผ่านส่วนต่อไปเพื่อเรียนรู้เกี่ยวกับการคำนวณเส้นทางและการเคลื่อนที่ของตัวละคร
สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
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
-- เพิ่มดัชนีเวย์พอยท์และย้ายไปยังเวย์พอยท์ต่อไป
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() คุณต้อง คำนวณ โดยเรียก Path:ComputeAsync() ด้วย Vector3 สำหรับจุดเริ่มต้นและจุดหมายทั้งสอง

สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
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
Path start/end marked on series of islands and bridges

รับเวย์พอยท์

เมื่อ Path ถูกคำนวณแล้ว มันจะมีซีรีส์ของ waypoints ปิดPath:GetWaypoints()

สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
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
Waypoints indicated across computed path
เวย์พอยท์ระบุในเส้นทางที่คำนวณได้

การเคลื่อนทางเส้นทาง

แต่ละเวย์พอยท์ประกอบด้วยทั้งตําแหน่ง ( ) และการกระทํา ( )เพื่อย้ายตัวละครที่มี Humanoid เช่นตัวละคร Roblox ทั่วไป วิธีที่ง่ายที่สุดคือการโทร Humanoid:MoveTo() จากจุดหมายไปยังจุดหมายโดยใช้อีเวนต์ MoveToFinished เพื่อตรวจจับเมื่อตัวละครถึงแต่ละจุดหมาย

สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
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
-- เพิ่มดัชนีเวย์พอยท์และย้ายไปยังเวย์พอยท์ต่อไป
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 จํานวนมากมีการเคลื่อนไหว; ชิ้นส่วนอาจเคลื่อนที่หรือล้มลง และพื้นอาจพังทลายสิ่งนี้สามารถบล็อกเส้นทางที่คำนวณได้และป้องกันไม่ให้ตัวละครถึงจุดหมายเพื่อจัดการกับสิ่งนี้คุณสามารถเชื่อมต่อเหตุการณ์ Path.Blocked และคำนวณเส้นทางอีกครั้งรอบสิ่งที่บล็อกมัน

สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
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

ตัวปรับเส้นทางค้นหา

โดยค่าเริ่มต้น จะส่งคืนเส้นทางที่สั้นที่สุดระหว่างจุดเริ่มต้นและจุดหมาย, ยกเว้นว่ามันพยายามหลีกเลี่ยงการกระโดดดูเหมือนไม่เป็นธรรมชาติในบางสถานการณ์ - อินสแตนซ์

Two paths indicated with the shorter path not necessarily more logical

เพื่อเพิ่มประสิทธิภาพการค้นหาเส้นทางต่อไป คุณสามารถใช้ ตัวปรับเปลี่ยนการค้นหาเส้นทาง เพื่อคำนวณเส้นทางที่ชาญฉลาดยิ่งขึ้นผ่านวัสดุต่างๆ รอบพื้นที่ที่กำหนด หรือผ่านอุปสรรค ได้

ตั้งค่าค่าใช้จ่ายวัสดุ

เมื่อทำงานกับ Terrain และ BasePart วัสดุคุณสามารถรวมตาราง Costs ภายใน CreatePath() เพื่อทำให้วัสดุบางอย่างเดินทางได้มากกว่าวัสดุอื่นวัสดุทั้งหมดมีค่าเริ่มต้นของ 1 และวัสดุใดๆ สามารถกำหนดได้ว่าไม่สามารถข้ามได้โดยการตั้งค่ามูลค่าของมันเป็น math.huge

คีย์ในตาราง Costs ควรเป็นชื่อสตริงที่แทนที่ชื่อ Enum.Material เช่น Water สำหรับ Enum.Material.Water

สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local path = PathfindingService:CreatePath({
Costs = {
Water = 20,
Mud = 5,
Neon = math.huge
}
})

ทำงานกับภูมิภาค

ในบางกรณี ความชอบของวัสดุ ไม่เพียงพอตัวอย่างเช่นคุณอาจต้องการให้ตัวละครหลีกเลี่ยงภูมิภาคที่กําหนดไว้ **** ไม่ว่าจะเป็นวัสดุที่อยู่ใต้เท้าสามารถทำได้โดยการเพิ่มวัตถุ PathfindingModifier ให้กับส่วน

  1. สร้างส่วน Anchored รอบภูมิภาคที่เป็นอันตรายและตั้งค่าคุณสมบัติ CanCollide เป็น ปิด

    Anchored part defining a region to apply a pathfinding modifier to
  2. ใส่ตัวอย่าง PathfindingModifier ลงในส่วน ค้นหาคุณสมบัติ Label ของมัน และกำหนดชื่อที่มีความหมายเช่น DangerZone

    PathfindingModifier instance with Label property set to DangerZone
  3. รวมโต๊ะ Costs ภายใน CreatePath() ที่มีกุญแจที่ตรงกันและมูลค่าเลขที่เกี่ยวข้องตัวปรับเปลี่ยนสามารถกำหนดได้ว่าไม่สามารถข้ามได้โดยการตั้งค่ามูลค่าเป็น math.huge

    สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local Workspace = game:GetService("Workspace")
    local path = PathfindingService:CreatePath({
    Costs = {
    DangerZone = math.huge
    }
    })

เพิกเฉยอุปสรรค

ในบางกรณีมันเป็นประโยชน์ที่จะค้นหาเส้นทางผ่านอุปสรรคแข็งเหมือนว่าพวกเขาไม่มีอยู่สิ่งนี้ช่วยให้คุณสามารถคำนวณเส้นทางผ่านตัวบล็อกทางกายภาพที่เฉพาะเจาะจงได้ เมื่อเทียบกับการคำนวณที่ล้มเหลวโดยสิ้นเชิง

  1. สร้างส่วน Anchored รอบวัตถุและตั้งค่าคุณสมบัติ CanCollide เป็น ปิด

    Anchored part defining a region to apply a pathfinding modifier to
  2. ใส่ตัวอย่าง PathfindingModifier บนส่วนและเปิดใช้งานคุณสมบัติ PassThrough ของมัน

    PathfindingModifier instance with PassThrough property enabled

    ตอนนี้เมื่อเส้นทางถูกคำนวณจาก NPC ซอมบี้ไปยังตัวละครผู้เล่นเส้นทางจะขยายไปเกินประตูและคุณสามารถส่งคำขอให้ซอมบี้เดินทางผ่านได้แม้ว่าซอมบี้จะไม่สามารถเปิดประตูได้ แต่มันจะตอบสนองเหมือนว่า "ได้ยิน" ตัวละครด้านหลังประตู

    Zombie NPC path passing through the previously blocking door

ลิงค์ค้นหาเส้นทาง

บางครั้งจำเป็นต้องหาเส้นทางข้ามพื้นที่ที่ไม่สามารถเดินทางได้ตามปกติ เช่น ข้ามหุบเขา และดำเนินการด้วยการกระทำที่กำหนดเองเพื่อไปถึงจุดหมายต่อไปสิ่งนี้สามารถทำได้ผ่านวัตถุ PathfindingLink

โดยใช้ตัวอย่างเกาะจากด้านบนคุณสามารถทำให้ตัวแทนใช้เรือแทนการเดินข้ามสะพานทั้งหมด

PathfindingLink showing how an agent can use a boat instead of walking across all of the bridges

เพื่อสร้าง PathfindingLink โดยใช้ตัวอย่างนี้:

  1. เพื่อช่วยในการวาดภาพและการแก้ไขข้อผิดพลาด เปิดใช้งาน ลิงก์ค้นหาเส้นทาง จากแดชบอร์ด ตัวเลือกการแสดงผล ในมุมบนขวาของหน้าต่าง 3D มุมมอง

  2. สร้างสอง Attachments , หนึ่งบนที่นั่งเรือและหนึ่งใกล้จุดลงจอดของเรือ

    Attachments created for pathfinding link's start and end
  3. สร้างวัตถุ PathfindingLink ในพื้นที่ทำงานจากนั้นกำหนดค่า แนบเนียน0 และ แนบเนียน1 คุณสมบัติให้กับแนบเนียนเริ่มต้นและสิ้นสุดตามลำดับ

    Attachment0/Attachment1 properties of a PathfindingLink PathfindingLink visualized in the 3D world
  4. กำหนดชื่อที่มีความหมายเช่น UseBoat ให้กับคุณสมบัติ Label ของมันชื่อนี้ใช้เป็นธงในสคริปต์การค้นหาเส้นทางเพื่อเรียกการดำเนินการที่กําหนดเองเมื่อตัวแทนถึงจุดเชื่อมต่อเริ่มต้น

    Label property specified for PathfindingLink
  5. รวมโต๊ะ Costs ภายใน CreatePath() ที่มีทั้งคีย์ Water และคีย์ที่กำหนดเองที่ตรงกับชื่อคุณสมบัติ Labelกำหนดคีย์ที่กําหนดเองมีค่าต่ํากว่า Water

    สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local Workspace = game:GetService("Workspace")
    local path = PathfindingService:CreatePath({
    Costs = {
    Water = 20,
    UseBoat = 1
    }
    })
  6. ในอีเวนต์ที่จะยิงเมื่อถึงเวย์พอยท์ เพิ่มการตรวจสอบแบบกําหนดเองสําหรับชื่อตัวแก้ไข Label และดําเนินการต่างจาก Humanoid:MoveTo() ในกรณีนี้โดยเรียกฟังก์ชันเพื่อนั่งตัวแทนในเรือ, ย้ายเรือข้ามน้ํา, และดําเนินเส้นทางของตัวแทนต่อเมื่อมาถึงเกาะปลายทาง

    สคริปท้องถิ่น - การค้นหาเส้นทางตัวละคร

    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local Workspace = game:GetService("Workspace")
    local path = PathfindingService:CreatePath({
    Costs = {
    Water = 20,
    UseBoat = 1
    }
    })
    local player = Players.LocalPlayer
    local character = player.Character
    local humanoid = character:WaitForChild("Humanoid")
    local TEST_DESTINATION = Vector3.new(228.9, 17.8, 292.5)
    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
    -- เพิ่มดัชนีเวย์พอยท์และย้ายไปยังเวย์พอยท์ต่อไป
    nextWaypointIndex += 1
    -- ใช้เรือหากฉลากเส้นทางเป็น "ใช้เรือ"; มิฉะนั้นย้ายไปยังจุดหมายถัดไป
    if waypoints[nextWaypointIndex].Label == "UseBoat" then
    useBoat()
    else
    humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
    end
    else
    reachedConnection:Disconnect()
    blockedConnection:Disconnect()
    end
    end)
    end
    -- เริ่มต้นย้ายไปยังจุดหมายที่สอง (จุดหมายแรกคือจุดเริ่มต้นเส้นทาง; ข้ามไป)
    nextWaypointIndex = 2
    humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
    else
    warn("Path not computed!", errorMessage)
    end
    end
    function useBoat()
    local boat = Workspace.BoatModel
    humanoid.Seated:Connect(function()
    -- เริ่มเคลื่อนเรือถ้าตัวแทนนั่งอยู่
    if humanoid.Sit then
    task.wait(1)
    boat.CylindricalConstraint.Velocity = 5
    end
    -- ตรวจจับตําแหน่งข้อจํากัดในความสัมพันธ์กับเกาะ
    local boatPositionConnection
    boatPositionConnection = RunService.PostSimulation:Connect(function()
    -- หยุดเรือเมื่ออยู่ใกล้เกาะ
    if boat.CylindricalConstraint.CurrentPosition >= 94 then
    boatPositionConnection:Disconnect()
    boat.CylindricalConstraint.Velocity = 0
    task.wait(1)
    -- ยกเลิกตัวแทนและดำเนินการต่อไปยังจุดหมาย
    humanoid.Sit = false
    humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
    end
    end)
    end)
    end
    followPath(TEST_DESTINATION)

การสตรีมความสอดคล้อง

การสตรีมตัวอย่างในประสบการณ์ เป็นคุณสมบัติที่ทรงพลังที่โหลดและถอด 3D เนื้อหาได้อย่างไดนามิกเมื่อตัวละครของผู้เล่นเคลื่อนที่ไปทั่วโลกเมื่อพวกเขาสำรวจพื้นที่ 3D ชุดย่อยใหม่ของสตรีมพื้นที่จะไหลไปยังอุปกรณ์ของพวกเขาและบางชุดย่อยที่มีอยู่อาจไหลออก

พิจารณาแนวทางที่ดีที่สุดต่อไปนี้สำหรับการใช้ PathfindingService ในประสบการณ์ที่เปิดใช้งานการสตรีม:

  • การสตรีมสามารถบล็อกหรือปลดบล็อกเส้นทางที่กำหนดเป็นตัวละครขณะเคลื่อนที่ไปตามมันตัวอย่างเช่น ในขณะที่ตัวละครวิ่งผ่านป่า ต้นไม้อาจสตรีมในสถานที่ข้างหน้าพวกเขาและขัดขวางเส้นทางเพื่อให้การค้นหาเส้นทางทำงานได้อย่างราบรื่นกับการสตรีม จึงเป็นที่แนะนำอย่างยิ่งว่าคุณควรใช้เทคนิคการจัดการเส้นทาง ที่ถูกบล็อก และคำนวณเส้นทางอีกครั้งเมื่อจำเป็น

  • วิธีการทั่วไปในการค้นหาเส้นทางคือการใช้พิกัดของวัตถุที่มีอยู่สําหรับการคํานวณ , เช่นการตั้งเส้นทางจุดหมายไปยังตําแหน่งของรูปแบบ หีบสมบัติ ที่มีอยู่ในโลกวิธีนี้สอดคล้องกับด้านเซิร์ฟเวอร์อย่างเต็มที่ Scripts เนื่องจากเซิร์ฟเวอร์มีมุมมองเต็มของโลกตลอดเวลา แต่ LocalScripts และ ModuleScripts ที่ทำงานบนไคลเอนต์อาจล้มเหลวหากพยายามคำนวณเส้นทางไปยังวัตถุที่ไม่ถูกสตรีมเข้ามา

    เพื่อแก้ปัญหานี้ พิจารณาการตั้งเป้าหมายเป็นตำแหน่งของ BasePart ภายในรูปแบบ ถาวรโมเดลถาวรโหลดเร็วหลังจากที่ผู้เล่นเข้าร่วมและพวกเขาไม่เคยสตรีมออก ดังนั้นสคริปต์ด้านคลายสามารถเชื่อมต่อกับเหตุการณ์ PersistentLoaded และเข้าถึงโมเดลได้อย่างปลอดภัยเพื่อสร้างเวย์พอยท์หลังจากเหตุการณ์เกิดขึ้น