การค้นหาเส้นทาง

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

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

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

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

มุมมองใกล้ของมุมมอง 3D พร้อมปุ่ม Visualization Options ที่ระบุในมุมขวาบน

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

เมชการนำทางที่แสดงใน Studio

การดำเนินการ

แม้ว่าการค้นหาเส้นทางสามารถดำเนินการได้หลายวิธีโดยใช้ PathfindingService และวิธีการที่เกี่ยวข้อง เช่น CreatePath(), ส่วนนี้จะใช้สคริปการค้นหาเส้นทางสำหรับตัวละครของผู้เล่น

เพื่อลองทดสอบในขณะที่อ่าน:

  1. สำคัญ
    ใน Explorer ให้เลือกคอนเทนเนอร์ StarterPlayer จากนั้นในหน้าต่าง Properties ตั้งค่า DevComputerMovementMode และ DevTouchMovementMode เป็น Scriptable

  2. คัดลอกโค้ดต่อไปนี้ไปยัง LocalScript ภายใน StarterCharacterScripts หรือ รับแพ็กเกจนี้ และวางมันไว้ใน StarterCharacterScripts

    PlayerPathFollow (LocalScript in StarterCharacterScripts)

    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local DESTINATION = Vector3.new(20, 0.5, 20)
    local GROUND_WAIT = 0.01
    local VELOCITY_MULTIPLIER = 0.0625
    local path = PathfindingService:CreatePath({
    AgentCanClimb = true,
    Costs = {
    Water = 20
    }
    })
    local character = script.Parent
    local humanoid = character:WaitForChild("Humanoid")
    local waypoints
    local nextWaypointIndex
    local blockedConnection
    local currentWaypointReachedConnection
    local currentWaypointPlaneNormal = Vector3.zero
    local currentWaypointPlaneDistance = 0
    local pathfinderWorking = false
    local function disconnectCurrentWaypointReachedConnection()
    if not currentWaypointReachedConnection then return end
    currentWaypointReachedConnection:Disconnect()
    currentWaypointReachedConnection = nil
    end
    local function isCurrentWaypointReached()
    if humanoid.FloorMaterial == Enum.Material.Air then
    return false
    end
    local reached = false
    if currentWaypointPlaneNormal ~= Vector3.zero then
    -- คำนวณระยะทางจากฮิวมานอยด์ไปยังระนาบจุดหมาย
    local dist = currentWaypointPlaneNormal:Dot(humanoid.RootPart.Position) - currentWaypointPlaneDistance
    -- คำนวณส่วนประกอบของความเร็วของฮิวมานอยด์ที่มุ่งไปที่ระนาบ
    local velocity = -currentWaypointPlaneNormal:Dot(humanoid.RootPart.Velocity)
    -- คำนวณเกณฑ์จากระนาบจุดหมายตามความเร็วของฮิวมานอยด์
    local threshold = math.max(1.0, VELOCITY_MULTIPLIER * velocity)
    -- ถือว่าถึงจุดหมายหากน้อยกว่าเกณฑ์ในด้านหน้า
    reached = dist < threshold
    else
    reached = true
    end
    if reached then
    currentWaypointPlaneNormal = Vector3.zero
    currentWaypointPlaneDistance = 0
    moveToNextWaypoint()
    end
    end
    local function calculateNextWaypointApproach()
    nextWaypointIndex += 1
    if nextWaypointIndex > #waypoints then
    return false
    end
    local currentWaypoint = waypoints[nextWaypointIndex - 1]
    local nextWaypoint = waypoints[nextWaypointIndex]
    -- สร้างระนาบจุดหมายจากจุดต่อไปไปยังปัจจุบัน
    currentWaypointPlaneNormal = currentWaypoint.Position - nextWaypoint.Position
    -- ตั้งนอร์มอลตั้งฉากกับระนาบ Y เมื่อไม่ปีนขึ้น
    if nextWaypoint.Label ~= "Climb" then
    currentWaypointPlaneNormal = Vector3.new(currentWaypointPlaneNormal.X, 0, currentWaypointPlaneNormal.Z)
    end
    if currentWaypointPlaneNormal.Magnitude > 0.000001 then
    currentWaypointPlaneNormal = currentWaypointPlaneNormal.Unit
    currentWaypointPlaneDistance = currentWaypointPlaneNormal:Dot(nextWaypoint.Position)
    end
    return true
    end
    local function resetWaypointData()
    humanoid:Move(Vector3.zero)
    currentWaypointPlaneNormal = Vector3.zero
    currentWaypointPlaneDistance = 0
    disconnectCurrentWaypointReachedConnection()
    pathfinderWorking = false
    end
    local function waitForGround()
    while humanoid.FloorMaterial == Enum.Material.Air do
    task.wait(GROUND_WAIT)
    end
    end
    function moveToNextWaypoint()
    if calculateNextWaypointApproach() then
    disconnectCurrentWaypointReachedConnection()
    currentWaypointReachedConnection = RunService.Heartbeat:Connect(isCurrentWaypointReached)
    local nextWaypointPosition = waypoints[nextWaypointIndex].Position
    local nextWaypointAction = waypoints[nextWaypointIndex].Action
    humanoid:Move(nextWaypointPosition - humanoid.RootPart.Position)
    if waypoints[nextWaypointIndex + 1] and waypoints[nextWaypointIndex + 1].Label == "UseBoat" then
    nextWaypointIndex += 1
    -- เรียกใช้ฟังก์ชันที่คุณกำหนดเองเพื่อทำให้ตัวแทนใช้เรือ
    elseif nextWaypointAction == Enum.PathWaypointAction.Jump then
    humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
    while humanoid.FloorMaterial ~= Enum.Material.Air do
    task.wait(GROUND_WAIT)
    end
    humanoid:Move(nextWaypointPosition - humanoid.RootPart.Position)
    end
    else
    resetWaypointData()
    end
    end
    local function findStartingPoint(waypoints)
    nextWaypointIndex = 1
    while nextWaypointIndex + 1 <= #waypoints do
    local dist = waypoints[nextWaypointIndex + 1].Position - humanoid.RootPart.Position
    dist = Vector3.new(dist.X, 0, dist.Z)
    if dist.magnitude >= 2 then
    return
    end
    nextWaypointIndex += 1
    end
    end
    local function followPath()
    -- คำนวณเส้นทาง
    pathfinderWorking = true
    waitForGround()
    local success, errorMessage = pcall(function()
    path:ComputeAsync(character.PrimaryPart.Position, DESTINATION)
    end)
    if not success or path.Status ~= Enum.PathStatus.Success then
    warn("ไม่สามารถคำนวณเส้นทางได้!", errorMessage)
    return
    end
    -- รับทางที่เป็นไปได้
    waypoints = path:GetWaypoints()
    -- ตรวจสอบว่าทางติดขัด
    blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
    -- ตรวจสอบว่ามีอุปสรรคอยู่ไกลลงไปในเส้นทาง
    if blockedWaypointIndex >= nextWaypointIndex then
    -- หยุดการตรวจจับการติดขัดจนกว่าจะมีการคำนวณใหม่
    blockedConnection:Disconnect()
    resetWaypointData()
    -- เรียกฟังก์ชันเพื่อคำนวณเส้นทางใหม่
    followPath()
    end
    end)
    findStartingPoint(waypoints)
    moveToNextWaypoint()
    end
    followPath()
  3. แก้ไขตัวแปร DESTINATION (

    บรรทัด 5
    ) เป็นจุดหมาย Vector3 ที่ตัวละครผู้เล่นสามารถไปถึงได้ในโลก 3D

  4. ดำเนินการตามส่วนถัดไปเพื่อเรียนรู้เกี่ยวกับการคำนวณเส้นทางและการเคลื่อนที่ของตัวละคร

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

การค้นหาเส้นทางเริ่มต้นผ่าน PathfindingService และวิธี CreatePath() (

บรรทัด 9–14
). วิธีนี้รับตารางของพารามิเตอร์ที่ไม่บังคับซึ่งมีผลต่อการเคลื่อนที่ของตัวละคร (ตัวแทน) ตามเส้นทาง

คีย์คำบรรยายประเภทค่าเริ่มต้น
AgentRadiusรัศมีของตัวแทน เป็นหน่วยสตัด สำหรับการกำหนดการแยกตัวจากอุปสรรคอย่างน้อยที่สุดinteger2
AgentHeightความสูงของตัวแทน เป็นหน่วยสตัด พื้นที่ว่างที่มีขนาดเล็กกว่านี้ เช่น พื้นที่ใต้บันได จะถูกทำเครื่องหมายว่าไม่สามารถผ่านได้integer5
AgentCanJumpกำหนดว่าสามารถกระโดดในระหว่างการค้นหาเส้นทางได้หรือไม่booleantrue
AgentCanClimbกำหนดว่าสามารถปีน TrussParts ในระหว่างการค้นหาเส้นทางได้หรือไม่ เส้นทางที่สามารถปีนได้มี Label ชื่อว่า Climb และ ค่าใช้จ่าย สำหรับเส้นทางที่สามารถปีนได้คือ 1 โดยเริ่มต้นbooleanfalse
WaypointSpacingระยะห่างระหว่างจุดทางกึ่งกลางในเส้นทาง หากตั้งค่าเป็น math.huge จะไม่มีจุดทางกึ่งกลางnumber4
Costsตารางของวัสดุหรือ PathfindingModifiers ที่กำหนดและค่าใช้จ่ายในการเดินทางผ่าน มีประโยชน์สำหรับทำให้ตัวแทนชอบวัสดุ/พื้นที่บางประเภทมากกว่าชนิดอื่น ดูรายละเอียดที่ ตัวแก้ไขtablenil

การคำนวณเส้นทาง

หลังจากที่คุณสร้างเส้นทางที่ถูกต้องสาหรับ CreatePath() แล้ว มันต้องถูก คำนวณ โดยเรียก Path:ComputeAsync() ด้วย Vector3 ทั้งสำหรับจุดเริ่มต้นและจุดหมาย (

บรรทัด 133–139
).

จุดเริ่มต้น/จุดสิ้นสุดของเส้นทางถูกทำเครื่องหมายผ่านสะพานสองแห่ง

เมื่อ Path ถูกคำนวณ มันจะมีชุดของ จุดทาง ที่แสดงเส้นทางจากจุดเริ่มต้นไปยังจุดสิ้นสุด จุดเหล่านี้สามารถรวบรวมได้ด้วยวิธี Path:GetWaypoints() (

บรรทัด 142
). อาร์เรย์ที่ส่งกลับจะจัดเรียงตามลำดับของจุดทางจากจุดเริ่มต้นไปจนถึงจุดสิ้นสุดของเส้นทาง

จุดทางที่แสดงอยู่ตามเส้นทางที่คำนวณ
จุดทางที่แสดงอยู่ตามเส้นทางที่คำนวณ

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

แต่ละ PathWaypoint ประกอบด้วยทั้ง Position (Vector3) และ Action (PathWaypointAction). เพื่อเคลื่อนที่ตัวละครที่มี Humanoid, เช่น ตัวละคร Roblox ปกติ วิธีที่ดีที่สุดคือเรียกใช้ Humanoid:Move() จากจุดทางไปยังจุดทางและใช้การกลับคืนของสคริปต์ isCurrentWaypointReached() (

บรรทัด 32–56
) เพื่อตรวจจับเมื่อใดที่ตัวละครถึงจุดทางแต่ละจุด

เส้นทางที่ถูกบล็อก

โลกใน Roblox หลายแห่งเป็นแบบพลศาสตร์; บางส่วนอาจเคลื่อนที่หรือหล่นและพื้นอาจถล่ม สิ่งนี้สามารถบล็อกเส้นทางที่เผามาและป้องกันไม่ให้ตัวละครถึงจุดหมายของตน เพื่อจัดการกับสิ่งนี้ คุณสามารถเชื่อมต่อกับเหตุการณ์ Path.Blocked และคำนวณเส้นทางใหม่รอบๆ สิ่งที่บล็อกมัน (

บรรทัด 145–154
).

ตัวแก้ไขการค้นหาเส้นทาง

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

เส้นทางสองเส้นที่แสดงเส้นทางที่สั้นกว่าไม่จำเป็นต้องสมเหตุสมผลมากกว่า

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

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

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

คีย์ในตาราง Costs ควรเป็นชื่อ string ที่แสดงถึงชื่อของ Enum.Material, เช่น Water สำหรับ Enum.Material.Water หรือ CrackedLava สำหรับ Enum.Material.CrackedLava.

PlayerPathFollow (LocalScript)

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local DESTINATION = Vector3.new(20, 0.5, 20)
local GROUND_WAIT = 0.01
local VELOCITY_MULTIPLIER = 0.0625
local path = PathfindingService:CreatePath({
AgentCanClimb = true,
Costs = {
Water = 20, CrackedLava = 100, Slate = 20
}
})

กำหนดค่าพื้นที่

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

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

    ส่วนที่ถูกยึดกำหนดพื้นที่สำหรับนำไปใช้กับตัวแก้ไขการค้นหาเส้นทาง
  2. แทรกอินสแตนซ์ PathfindingModifier ลงในส่วน ตรวจสอบคุณสมบัติ Label และกำหนดชื่อที่มีความหมายเช่น DangerZone.

    อินสแตนซ์ PathfindingModifier ที่มีคุณสมบัติ Label ตั้งค่าเป็น DangerZone
  3. รวมคีย์ DangerZone และค่าตัวเลขที่สัมพันธ์กับไว้ภายในตาราง Costs ของ CreatePath(). ตัวแก้ไขสามารถกำหนดเป็นไม่สามารถผ่านได้โดยการตั้งค่าค่าของมันเป็น math.huge.

    PlayerPathFollow (LocalScript)

    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local DESTINATION = Vector3.new(20, 0.5, 20)
    local GROUND_WAIT = 0.01
    local VELOCITY_MULTIPLIER = 0.0625
    local path = PathfindingService:CreatePath({
    AgentCanClimb = true,
    Costs = {
    DangerZone = math.huge, Water = 20, CrackedLava = 20, Slate = 20
    }
    })

ละเว้นอุปสรรค

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

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

    ส่วนที่ถูกยึดกำหนดพื้นที่สำหรับนำไปใช้กับตัวแก้ไขการค้นหาเส้นทาง
  2. แทรกอินสแตนซ์ PathfindingModifier ลงในส่วนและเปิดใช้งานคุณสมบัติ PassThrough.

    อินสแตนซ์ PathfindingModifier ที่มีคุณสมบัติ PassThrough เปิดใช้งานแล้ว

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

    เส้นทาง NPC ซอมบี้ผ่านประตูที่เคยบล็อกอยู่

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

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

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

PathfindingLink แสดงวิธีที่ตัวแทนสามารถใช้เรือได้

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

  1. ทางเลือก
    เปิดใช้งาน Pathfinding links จากวิจิตรมุมมอง Visualization Options ที่มุมขวาบนของมุมมอง 3D สิ่งนี้ช่วยในการแสดงภาพและดีบักเมื่อดำเนินการเชื่อมโยงการค้นหาเส้นทาง

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

    การยึดที่สร้างสำหรับจุดเริ่มต้นและจุดสิ้นสุดของลิงก์การค้นหาเส้นทาง
  3. สร้างวัตถุ PathfindingLink ในพื้นที่ทำงาน จากนั้นกำหนดคุณสมบัติ Attachment0 และ Attachment1 ให้กับการยึดเริ่มต้นและจุดสิ้นสุดตามลำดับ

    คุณสมบัติ Attachment0/Attachment1 ของ PathfindingLink. PathfindingLink ที่แสดงในโลก 3D.
  4. กำหนดชื่อที่มีความหมาย เช่น ใช้เรือ ให้กับคุณสมบัติ Label. ชื่อนี้จะถูกใช้เป็นสัญลักษณ์ในสคริปการค้นหาเส้นทางเพื่อเริ่มการกระทำที่กำหนดเองเมื่อเอเจนท์ถึงจุดเริ่มต้นของลิงก์

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

    PlayerPathFollow (LocalScript)

    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local DESTINATION = Vector3.new(20, 0.5, 20)
    local GROUND_WAIT = 0.01
    local VELOCITY_MULTIPLIER = 0.0625
    local path = PathfindingService:CreatePath({
    AgentCanClimb = true,
    Costs = {
    UseBoat = 2, Water = 20
    }
    })
  6. ในฟังก์ชัน moveToNextWaypoint() (

    บรรทัด 93–114
    ), การตรวจสอบที่กำหนดเองสำหรับชื่อโมดิฟายเออร์ Label สามารถใช้เพื่อดำเนินการที่แตกต่างจาก Humanoid:Move(); ในกรณีนี้ คุณอาจเรียกใช้ฟังก์ชันเพื่อทำให้ตัวแทนนั่งในเรือ นำเรือไปข้ามน้ำ ไล่ที่นั่งออกที่จุดลงจอดของเรือ และจากนั้นก็ดำเนินการเส้นทางของตัวแทนไปยังจุดหมายสุดท้าย

ความเข้ากันได้กับการสตรีม

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

พิจารณาแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้เมื่อใช้ PathfindingService ในเกมที่เปิดอยู่รอบ:

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

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

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

ข้อจำกัดและปัจจัยที่ทำให้ล้มเหลว

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

©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ