เทคนิคและการแปลง

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

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

คุณสมบัติการสตรีม

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

คุณสมบัติคำแนะนำ
EnableSLIMAvatarsใช้ Enabled เพื่อเรนเดอร์อวาตาร์แบบน้ำหนักเบาที่มีการเคลื่อนไหวเมื่อเหมาะสม ดูเพิ่มเติมเกี่ยวกับ SLIM avatars
ModelStreamingBehaviorใช้ Improved เพื่อเปิดใช้งานการสตรีมที่มีประสิทธิภาพที่สุดสำหรับ Models ที่มีผู้สืบทอด BasePart
StreamingIntegrityModeใช้ PauseOutsideLoadedArea เพื่อรักษาความสมบูรณ์ของการเล่นโดยไม่หยุดชะงักมากเกินไปหรือบ่อยเกินไป
StreamingMinRadiusใช้ค่าเริ่มต้นที่ 64 เพื่อเพิ่มประสิทธิภาพให้อินจินสามารถทำงานได้อย่างเหมาะสมสำหรับอุปกรณ์ที่มีประสิทธิภาพต่ำ
StreamingTargetRadiusใช้ค่าเริ่มต้นที่ 1024 เพื่อให้เกิดความสมดุลระหว่างการมองเห็นสำหรับผู้เล่นบนอุปกรณ์ที่มีประสิทธิภาพสูงและการใช้หน่วยความจำที่เหมาะสม
StreamOutBehaviorใช้ Opportunistic เพื่อให้ไคลเอ็นต์เก็บข้อมูลที่ไม่ใช้งานได้อย่างรวดเร็ว ลดการใช้หน่วยความจำอย่างมากและช่วยป้องกันการเกิดข้อผิดพลาดจากหน่วยความจำเต็ม

ระดับรายละเอียดของโมเดล

Model.LevelOfDetail ช่วยเติมเต็มเนื้อหาของ Model ที่ไม่ได้สตรีมด้วยส่วนผสมที่ง่ายหรืออิมโพสเตอร์เมช ซึ่งทำให้โลกดูสมบูรณ์ทางสายตา SLIM (Scalable Lightweight Interactive Model) มีประสิทธิภาพโดยเฉพาะ เพราะผู้เล่นมักไม่สามารถแยกแยะระหว่างเมช SLIM กับโมเดลต้นฉบับที่สตรีมเข้ามาได้

เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด:

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

โครงสร้างโมเดล

นอกเหนือจากการตั้ง ระดับรายละเอียดของโมเดล แล้ว โครงสร้างและการตั้งค่าของ Models มีผลกระทบอย่างมีนัยสำคัญต่อประสิทธิภาพของการสตรีม ขณะที่คุณสร้างหรือแปลงเกมที่มีอยู่:

  • ใช้โมเดลที่เป็นอะตอมสำหรับการจัดกลุ่มทางตรรกศาสตร์ — เมื่อสคริปต์ต้องเข้าถึงส่วนประกอบทั้งหมดในโมเดล ให้ตั้งค่า ModelStreamingMode เป็น Atomic ซึ่งช่วยให้สคริปต์ด้านไคลเอ็นต์สามารถเข้าถึงอินสแตนซ์ภายในโมเดลได้โดยปลอดภัยโดยไม่ต้องใช้ WaitForChild() มากเกินไป (แม้ว่าสคริปต์เหล่านี้จะต้องยังคงใช้ WaitForChild() สำหรับโมเดลอะตอมทั้งหมด)

  • ลดจำนวนโมเดลที่ติดอยู่ — โมเดลที่ ติดอยู่ จะโหลดหลังจากเข้าร่วมและไม่เคยสตรีมออกจะทำให้ใช้หน่วยความจำตลอดไป ตั้งค่า ModelStreamingMode ของโมเดลเป็น Persistent เฉพาะเมื่อมีความจำเป็นที่จะต้องรักษาให้สามารถใช้งานได้และเข้าถึงได้จากสคริปต์ตลอดเวลา

  • แยกโมเดลคอนเทนเนอร์ — รูปแบบการไม่สตรีมที่พบได้ทั่วไปคือไลน์ของ Model ขนาดใหญ่ที่มี NPCs, props หรือการจัดกลุ่มที่คล้ายกันอยู่ภายใน โมเดลคอนเทนเนอร์ลดประสิทธิภาพในการสตรีมภายใต้การสตรีมและไม่เหมาะสำหรับ ระดับรายละเอียดของโมเดล ซึ่งทำงานได้ดีที่สุดเมื่อมีอินสแตนซ์ที่ถูกจัดกลุ่มอย่างใกล้ชิด แยกโมเดลคอนเทนเนอร์ออกเป็นโมเดลขนาดเล็กที่มีส่วนประกอบใกล้กันหรือมีความสัมพันธ์ทางตรรกศาสตร์

  • ลดการซ้อนระบบโมเดล — การซ้อน โมเดลที่ติดตั้ง ภายใน โมเดลอะตอม จะบังคับให้โมเดลอะตอมทำงานเป็นโมเดลติดตั้ง ที่มีระบบลำดับที่แบนราบสามารถเข้าใจง่ายกว่าในระหว่างการสตรีม

SLIM avatars

อวาตาร์ภายนอกที่อยู่นอกเขตที่ถูกสตรีมโดยเริ่มจากจะไม่สามารถมองเห็นได้ตามค่าเริ่มต้น แต่การเปิดใช้งาน Workspace.EnableSLIMAvatars จะเรนเดอร์ Standard rig อวาตาร์ให้เป็นอวตาร์ที่มีน้ำหนักเบาและมีการเคลื่อนไหวเมื่อเหมาะสม โดยทั่วไปแล้ว เอนจิ้นจะ:

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

ระบบระดับรายละเอียดของอวาตาร์มีการปรับแต่งเฉพาะสำหรับอวาตาร์ ต่อไปนี้อธิบายว่าจะมีการประมวลผลอะไรและไม่ประมวลผลโดย SLIM:

รูปแบบสคริปต์

รูปแบบสคริปต์ต่อไปนี้มักได้รับผลกระทบจากการสตรีม กลยุทธ์ที่ถูกต้องขึ้นอยู่กับเจตนาของโค้ด ดังนั้นรูปแบบแต่ละรูปแบบจึงมีตัวเลือกหลายตัวเลือกไว้เมื่อเหมาะสม

ดัชนีโดยตรงไปยังผู้ส่งทอด

การเข้าถึงผู้ส่งทอดของ Workspace ด้วยตัวดำเนินการ . จะทำให้เกิดข้อผิดพลาดหากอินสแตนซ์ใด ๆ ในเส้นทางนั้นไม่ได้ถูกสตรีมเข้ามาในขณะนั้น สิ่งเดียวกันนี้ใช้ได้กับ FindFirstChild(), FindFirstChildWhichIsA(), และ FindFirstChildOfClass() ซึ่งจะคืนค่า nil หากลูกค้าไม่ได้อยู่

การค้นหา Descendant

local house1 = workspace:FindFirstChild("House1") -- nil หาก "House1" ยังไม่ได้ถูกสตรีมเข้ามา
local door = workspace.House1.Door -- ขัดข้องหาก "House1" หรือ "Door" ยังไม่ได้ถูกสตรีมเข้ามา

รูปแบบที่คล้ายคลึงกันคือการเข้าถึง Humanoid หรือผู้ส่งทอดตัวละครอื่น ๆ โดยตรงภายในการเชื่อมต่อ Player.CharacterAdded การสตรีมจะทำให้โมเดลตัวละครถูกสร้างเป็นลูกของ Workspace ก่อนที่ผู้ส่งทอดทั้งหมดจะถูกทำซ้ำ ดังนั้นการเข้าถึงโดยตรงจึงล้มเหลว

Descendant ของตัวละคร

local Players = game:GetService("Players")
local player = Players.LocalPlayer
player.CharacterAdded:Connect(function(character)
local humanoid = character.Humanoid
end)

หากสคริปต์ไม่สามารถดำเนินการต่อได้โดยไม่มีอินสแตนซ์ ให้รอด้วย WaitForChild():

การค้นหา Descendant

local house1 = workspace:WaitForChild("House1")
local door = house1:WaitForChild("Door")

อินสแตนซ์ที่ถูกส่งไปทางไกล

สัญญาณ RemoteEvent/RemoteFunction และอินสแตนซ์ที่มันอ้างอิงเดินทางอย่างอิสระ ดังนั้นสัญญาณจึงสามารถมาถึงที่ไคลเอ็นต์ก่อนที่อินสแตนซ์จะปรากฏ — หรืออินสแตนซ์อาจจะไม่ปรากฏเลย สาเหตุที่น่าจะเป็นสองประการ ได้แก่:

  • ภายใต้การสตรีม อาจมีความล่าช้าระหว่างเมื่อส่วน/โมเดลถูกสร้างบนเซิร์ฟเวอร์และเมื่อมันถูกทำซ้ำไปยังไคลเอ็นต์ ซึ่งทางการสตรีมอาจทำให้ส่วนที่มีการอ้างอิงโดย RemoteEvent/RemoteFunction ไม่มีอยู่เลย แม้กระทั่งในพื้นที่ที่ถูกสตรีม

  • การส่งอ้างอิงของส่วน/โมเดลจากเซิร์ฟเวอร์ไปยังไคลเอ็นต์ผ่านทาง RemoteEvent หรือ RemoteFunction เป็นการกำหนดให้ต้องมีการทำซ้ำอินสแตนซ์ไปยังไคลเอ็นต์ที่รับข้อมูล การส่งเส้นทางของอินสแตนซ์เป็นสตริงมีปัญหาเดียวกัน เนื่องจากเส้นทางนั้นอาจจะชี้ไปที่ตำแหน่งที่ไม่เกิดขึ้นในไคลเอ็นต์:

    สคริปต์ของไคลเอ็นต์

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
    remoteEvent.OnClientEvent:Connect(function(data)
    local checkpoint = data.checkpoint -- ข้อผิดพลาดหาก "checkpoint" ยังไม่ได้ถูกสตรีมเข้ามา
    local level = workspace.Levels[data.levelPath] -- ข้อผิดพลาดหากเส้นทางยังไม่ได้ถูกสตรีมเข้ามา
    end)

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

การไม่ซิงค์ของไคลเอ็นต์

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

ตัวอย่างเช่น การเปลี่ยนแปลงอินสแตนซ์ในท้องถิ่นจาก ReplicatedStorage ไปยัง Workspace จะทำให้สามารถสตรีมออกได้ การสร้างองค์ประกอบใหม่ในลักษณะเดียวกัน (Instance:Clone()) จาก ReplicatedStorage ไปยัง Workspace จะสร้างสำเนาเฉพาะที่เป็นของไคลเอ็นต์ ซึ่งจะไม่อยู่ภายใต้กระบวนการทำซ้ำของเซิร์ฟเวอร์และจะไม่ได้รับการอัปเดตคุณสมบัติจากอินสแตนซ์ที่เป็นของเซิร์ฟเวอร์ดั้งเดิม

แนวคิดเดียวกันนี้ใช้ได้เมื่อต้องเรียก Instance:Destroy() จากโมเดลที่เป็นของเซิร์ฟเวอร์ การละทิ้งอินสแตนซ์ในท้องถิ่น แต่ว่าเซิร์ฟเวอร์ยังคงมีอยู่ ดังนั้นมันจะถูกสตรีมเข้าใหม่อีกครั้งด้วยสถานะเดิมเมื่อมีสิทธิ์

การสตรีมเชิงรุก

เมื่อสถานที่ถัดไปของผู้เล่นสามารถคาดการณ์ได้ ให้เรียกใช้การโทรจากเซิร์ฟเวอร์ไปยัง Player:RequestStreamAroundAsync() เพื่อสตรีมพื้นที่ชั่วคราวสำหรับการโหลดชั่วคราว หรือใช้ Player:AddReplicationFocus() บนพื้นฐาน จำกัด สำหรับพื้นที่ที่ควรจะมีโหลดจนกว่าจะมีการปล่อยอย่างชัดเจน

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

สคริปต์จากเซิร์ฟเวอร์ - เทเลพอร์ตตัวละครของผู้เล่น

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- ขอให้สตรีมรอบพื้นที่เป้าหมาย
player:RequestStreamAroundAsync(teleportTarget)
-- เทเลพอร์ตตัวละคร
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- เรียกใช้ฟังก์ชันเทเลพอร์ตเมื่อไคลเอ็นต์ส่งสัญญาณเหตุการณ์ไปยังเซิร์ฟเวอร์
teleportEvent.OnServerEvent:Connect(teleportPlayer)

การอ่านคุณสมบัติของอินสแตนซ์

เมื่ออินสแตนซ์ถูกสตรีมออก การอัปเดตคุณสมบัติของมันจะไม่ถูกทำซ้ำไปยังไคลเอ็นต์นั้นอีกต่อไป การอ่านคุณสมบัติเช่น BasePart.Position ยังคงประสบความสำเร็จ แต่จะคืนค่าเป็นค่าที่ถูกทำซ้ำล่าสุดซึ่งอาจเก่ามาก


local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- ตำแหน่งอาจเก่าได้หาก "target" ได้ถูกสตรีมออกไป
local dist = (target.Position - player.Character.HumanoidRootPart.Position).Magnitude

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

รอในเส้นทางสำคัญ

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

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

การจัดการการเปลี่ยนแปลงสัญญาณ

สัญญาณเช่น Instance.ChildAdded/Instance.ChildRemoved และสัญญาณ CollectionService เช่น GetInstanceAddedSignal() หรือ GetInstanceRemovedSignal() จะถูกเรียกใช้เมื่อมีการสตรีมเข้า/ออก ซึ่งไม่สามารถแยกความแตกต่างจากการเกิดหรือการลบจริงได้ สคริปต์ที่รับข้อมูลไม่สามารถแยกความต่างจากสัญญาณเพียงอย่างเดียวได้ ดังนั้นตรรกะที่สมมุติว่ามีสัญญาณที่เกี่ยวข้องกับเหตุการณ์ "จริง" จะต้องได้รับการอัปเดต

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

การติดตามแอตทริบิวต์

local CollectionService = game:GetService("CollectionService")
local TAG_NAME = "ศัตรู"
CollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(enemy)
if not enemy:GetAttribute("Spawned") then
-- ตั้งค่าแอตทริบิวต์ "Spawned" สำหรับศัตรูในการปรากฏตัวครั้งแรก
enemy:SetAttribute("Spawned", true)
-- เล่นเสียง/เอฟเฟกต์ภาพสำหรับการเกิดครั้งแรกนี้
playSpawnEffects(enemy)
end
end)

การทำซ้ำในคอลเลกชัน

การทำซ้ำคอลเลกชันฝั่งไคลเอ็นต์เช่น Instance:GetChildren() และ Instance:GetDescendants() จะส่งค่าผลลัพธ์เฉพาะในกลุ่มผู้ส่งทอดที่สตรีมมาแล้วเท่านั้น แม้ว่าผู้ปกครองเองจะถูกทำซ้ำเสมอ เช่น Folder ที่อยู่โดยตรงภายใต้ Workspace ซึ่งมีคอลเลกชันของผู้ส่งทอดที่ไหลเข้าหรือออก


local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- โฟลเดอร์ "Homes" ถูกทำซ้ำเสมอแต่เด็กของมันจะถูกสตรีมเข้าหรือออก
-- ลูปนี้อาจพลาดบ้านที่ไม่ได้สตรีมอยู่ในขณะนี้
for _, home in workspace.Homes:GetChildren() do
if home.Settings.Owner.Value == player.Name then
return home
end
end

หากการระบุทั้งหมดเป็นสิ่งจำเป็น ให้ดำเนินการสแกนบนเซิร์ฟเวอร์และส่งผลลัพธ์ไปยังผู้เล่นผ่านทาง RemoteEvent หากจำเป็น

คิวรีเชิงพื้นที่

การค้นหาทางกายภาพภายในโปรเจคเช่น WorldRoot:Raycast(), WorldRoot:GetPartBoundsInBox(), และ Model:GetBoundingBox() จะสะท้อนเฉพาะเนื้อหาที่มีการไหลเข้ามาเท่านั้น รายละเอียดที่อยู่ที่ใช้จะไม่ทำให้การแก้ไขอักขระสำหรับข้อมูลที่ต้องทำ

ใช้เซิร์ฟเวอร์สำหรับคิวรีที่ผลลัพธ์จะต้องอยู่ที่ทั่วโลก เช่น การยิงว่า ผู้เล่นมีห้องมองระยะใกล้ไปยังเป้าหมายหรือไม่

รูปแบบอื่น ๆ

รูปแบบต่อไปนี้อาจนำมาใช้ได้เช่นกันและควรได้รับการพิจารณาอย่างรอบคอบ:

  • Sound หรือ AudioPlayer ที่อยู่ภายใต้วัตถุ 3D จะหยุดเมื่อวัตถุดังกล่าวสตรีมออก สำหรับเสียงบรรยากาศที่ควรรักษาเสมออย่างไรก็ตาม ให้วางตัวส่งสัญญาณไว้ภายใต้โมเดล ที่ติดตั้ง หรือในคอนเทนเนอร์ที่ไม่ใช่การสตรีม

  • วัตถุ UI ในเกม เช่น BillboardGui หรือ SurfaceGui รวมไปถึง เอฟเฟกต์ภาพ อย่างเช่น Beams หรือ Highlights ซึ่งมีอแดปเตอร์หรือติดตั้งสตรีมออกจะหยุดการเรนเดอร์ โดยทั่วไปก็เป็นพฤติกรรมที่ตั้งใจไว้ แต่คุณควรตรวจสอบ

  • เหตุการณ์ BasePart.Touched, ProximityPrompts, DragDetectors, และ ClickDetectors จะไม่ทำงานให้กับผู้เล่นที่ไคลเอ็นต์ของเขายังไม่ได้มีส่วนที่เกี่ยวข้องถูกสตรีมเข้า หากการมีส่วนร่วมต้องจะทำได้จากทุกระยะ โมเดลจำเป็นต้องเป็น ที่ติดตั้ง หรือกลไกการมีส่วนร่วมต้องมีการออกแบบใหม่

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

เงื่อนไขการทดสอบที่สมจริง

เมื่อ สคริปต์ได้รับการอัปเดต ทดสอบเกมอย่างละเอียด ปัญหาการสตรีมมักจะปรากฏเฉพาะที่ขอบของพื้นที่สตรีมหรือระหว่างการเปลี่ยนแปลง ดังนั้นการทดสอบทั้งหมดตั้งอยู่ใกล้จุดเกิดหรือที่รัศมีเป้าหมายเพียงครึ่งอาจไม่เพียงพอ

  • ทดสอบโดยใช้ Workspace.StreamingTargetRadius ที่ตั้งอยู่ที่ค่าต่ำสุด (64) ปัญหาการสตรีมบางประการจะเกิดขึ้นเมื่อพื้นที่ที่สตรีมนั้นมีขนาดเล็ก

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

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

  • ตรวจสอบหน้าต่าง Output และ Developer Console สำหรับข้อผิดพลาด เนื่องจากหลาย ๆ รูปแบบ script patterns จะผลิตข้อผิดพลาดแทนที่จะเงียบเสียง การให้ความสนใจโดยเฉพาะต่อข้อผิดพลาดในรูปแบบ attempt to index nil with ... ที่มักจะบ่งบอกถึงการขาดการเรียก WaitForChild()

  • เก็บและเปิดใช้งาน Tools, ยิงอาวุธ และกระตุ้นการมีส่วนร่วมในเกมที่แตกต่างกัน

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