ปรับปรุงประสิทธิภาพ

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

หน้านี้อธิบายปัญหาประสิทธิภาพทั่วไปและแนวทางปฏิบัติที่ดีที่สุดในการบรรเทา

การคำนวณสคริปต์

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

ปัญหาทั่วไป

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

การบรรเทา

  • เรียกใช้โค้ดในเหตุการณ์ RunService อย่างประหยัด โดยจำกัดการใช้งานในกรณีที่การเรียกใช้งานที่มีความถี่สูงเป็นสิ่งจำเป็น (เช่น การอัปเดตกล้อง) คุณสามารถดำเนินการโค้ดส่วนใหญ่ในเหตุการณ์อื่น ๆ หรือในลูปที่มีความถี่น้อยกว่า
  • แบ่งงานขนาดใหญ่หรือมีค่าใช้จ่ายสูงโดยใช้ task.wait() เพื่อกระจายงานไปยังหลายเฟรม
  • ระบุและปรับแต่งการดำเนินการที่มีค่าใช้จ่ายสูงโดยไม่จำเป็นและใช้ มัลติเทรดดิ้ง สำหรับงานที่มีค่าใช้จ่ายสูงในการคำนวณที่ไม่จำเป็นต้องเข้าถึงโมเดลข้อมูล
  • สคริปต์บางตัวที่ทำงานบนเซิร์ฟเวอร์สามารถได้รับประโยชน์จาก การสร้างโค้ดเนทีฟ ซึ่งเป็นธงง่าย ๆ ที่คอมไพล์สคริปต์เป็นโค้ดเครื่องแทนที่จะเป็นไบต์โค้ด
  • หากเซิร์ฟเวอร์ของคุณยังคงใช้ CPU หมดหลังจากที่คุณปรับแต่งแล้ว คุณสามารถสำรอง CPU เพิ่มเติมได้ด้วย Extended Services for Compute

ขอบเขต MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง
RunService.PreRenderโค้ดที่ดำเนินการในเหตุการณ์ PreRender
RunService.PreSimulationโค้ดที่ดำเนินการในเหตุการณ์ Stepped
RunService.PostSimulationโค้ดที่ดำเนินการในเหตุการณ์ Heartbeat
RunService.Heartbeatโค้ดที่ดำเนินการในเหตุการณ์ Heartbeat

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการดีบักสคริปต์โดยใช้ MicroProfiler โปรดดูที่ไลบรารี debug ซึ่งรวมถึงฟังก์ชันสำหรับการติดแท็กโค้ดเฉพาะและเพิ่มความเฉพาะเจาะจง เช่น debug.profilebegin และ debug.profileend วิธีการ API ของ Roblox หลายวิธีที่เรียกโดยสคริปต์ยังมีแท็ก MicroProfiler ที่เกี่ยวข้องซึ่งสามารถให้สัญญาณที่มีประโยชน์

การใช้หน่วยความจำของสคริปต์

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

ค่าหน่วยความจำต่อไปนี้ใน Developer Console อาจบ่งชี้ถึงปัญหาที่ต้องการการตรวจสอบเพิ่มเติม:

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

ปัญหาทั่วไป

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

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

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

    Example
    local playerInfo = {}
    Players.PlayerAdded:Connect(function(player)
    playerInfo[player] = {} -- ข้อมูลบางอย่าง
    end)

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

การบรรเทา

เพื่อทำความสะอาดค่าที่ใช้ทั้งหมดเพื่อป้องกันการรั่วไหลของหน่วยความจำ:

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

    • ตัดการเชื่อมต่อด้วยตนเองโดยใช้ฟังก์ชัน Disconnect()
    • ทำลายอินสแตนซ์ที่เหตุการณ์เป็นของด้วยฟังก์ชัน Destroy()
    • ทำลายวัตถุสคริปต์ที่การเชื่อมต่อย้อนกลับไปถึง
  • ลบวัตถุผู้เล่นและตัวละครหลังจากออก - เปิดใช้งาน Workspace.PlayerCharacterDestroyBehavior เพื่อทำลายวัตถุผู้เล่นและโมเดลตัวละครโดยอัตโนมัติหลังจากที่ผู้ใช้ออก หากคุณต้องการ คุณสามารถทำความสะอาดด้วยตนเอง:

    Example player and character cleanup
    local Players = game:GetService("Players")
    Players.PlayerAdded:Connect(function(player)
    player.CharacterRemoving:Connect(function(character)
    task.defer(character.Destroy, character)
    end)
    end)
    Players.PlayerRemoving:Connect(function(player)
    task.defer(player.Destroy, player)
    end)

การคำนวณฟิสิกส์

การจำลองฟิสิกส์ที่มากเกินไปอาจเป็นสาเหตุหลักของการเพิ่มขึ้นของเวลาในการคำนวณต่อเฟรมทั้งในเซิร์ฟเวอร์และลูกค้า

ปัญหาทั่วไป

  • ความถี่ของการก้าวฟิสิกส์ที่มากเกินไป - โดยค่าเริ่มต้น พฤติกรรมการก้าวอยู่ใน โหมดปรับตัว ซึ่งฟิสิกส์จะก้าวที่ 60 Hz, 120 Hz หรือ 240 Hz ขึ้นอยู่กับความซับซ้อนของกลไกฟิสิกส์

    โหมดคงที่ที่มีความแม่นยำของฟิสิกส์ที่ดีขึ้นยังมีให้ ซึ่งบังคับให้การประกอบฟิสิกส์ทั้งหมดก้าวที่ 240 Hz (สี่ครั้งต่อเฟรม) สิ่งนี้ส่งผลให้มีการคำนวณมากขึ้นอย่างมีนัยสำคัญในแต่ละเฟรม

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

  • การตรวจจับการชนที่แม่นยำเกินไป - ส่วนเมชมีคุณสมบัติ CollisionFidelity สำหรับการตรวจจับการชนซึ่งมีโหมดที่หลากหลายพร้อมระดับผลกระทบด้านประสิทธิภาพที่แตกต่างกัน โหมดการตรวจจับการชนที่แม่นยำสำหรับส่วนเมชมีค่าใช้จ่ายด้านประสิทธิภาพที่แพงที่สุดและใช้เวลานานกว่าในการคำนวณ

การบรรเทา

  • ยึดส่วนที่ไม่ต้องการการจำลอง - ยึดส่วนทั้งหมดที่ไม่จำเป็นต้องขับเคลื่อนด้วยฟิสิกส์ เช่น NPC แบบสถิต

  • ใช้การก้าวฟิสิกส์แบบปรับตัว - การก้าวแบบปรับตัวจะปรับอัตราการคำนวณฟิสิกส์สำหรับกลไกฟิสิกส์โดยอัตโนมัติ ทำให้การอัปเดตฟิสิกส์สามารถทำได้ในบางกรณีน้อยลง

  • ลดความซับซ้อนของกลไก

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

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

    • สำหรับวัตถุขนาดเล็กถึงขนาดกลาง ให้ใช้ความแม่นยำแบบกล่องหรือฮัลล์ ขึ้นอยู่กับรูปร่าง

    • สำหรับวัตถุขนาดใหญ่และซับซ้อนมาก ให้สร้างการชนแบบกำหนดเองโดยใช้ส่วนที่มองไม่เห็นเมื่อเป็นไปได้

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

    • คุณสามารถเรนเดอร์เรขาคณิตการชนเพื่อวัตถุประสงค์ในการดีบักใน Studio โดยการเปิดใช้งาน Collision fidelity จาก Visualization Options วิดเจ็ตในมุมขวาบนของมุมมอง 3D

      นอกจากนี้ คุณสามารถใช้ตัวกรอง CollisionFidelity=PreciseConvexDecomposition กับ Explorer ซึ่งจะแสดงจำนวนส่วนเมชทั้งหมดที่มีความแม่นยำและช่วยให้คุณเลือกได้ง่าย

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

ขอบเขต MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง
physicsSteppedการคำนวณฟิสิกส์โดยรวม
worldStepการก้าวฟิสิกส์แบบไม่ต่อเนื่องที่ดำเนินการในแต่ละเฟรม

การใช้หน่วยความจำฟิสิกส์

การเคลื่อนไหวของฟิสิกส์และการตรวจจับการชนใช้หน่วยความจำ ส่วนเมชมีคุณสมบัติ CollisionFidelity ที่กำหนดวิธีการที่ใช้ในการประเมินขอบเขตการชนของเมช

ปัญหาทั่วไป

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

หากคุณเห็นระดับการใช้หน่วยความจำสูงภายใต้ PhysicsParts คุณอาจต้องสำรวจการลด ความแม่นยำในการตรวจจับการชน ของวัตถุในเกมของคุณ

วิธีการบรรเทา

เพื่อลดหน่วยความจำที่ใช้สำหรับความแม่นยำในการตรวจจับการชน:

  • สำหรับส่วนที่ไม่ต้องการการชน ให้ปิดการชนโดยการตั้งค่า BasePart.CanCollide, BasePart.CanTouch และ BasePart.CanQuery เป็น false
  • ลดความแม่นยำของการชนโดยใช้การตั้งค่า CollisionFidelity Box มีค่าใช้จ่ายหน่วยความจำต่ำสุด และ Default และ Precise จะมีค่าใช้จ่ายสูงกว่าโดยทั่วไป
    • โดยทั่วไปปลอดภัยที่จะตั้งค่าความแม่นยำในการชนของส่วนที่ยึดไว้ขนาดเล็กเป็น Box
    • สำหรับเมชขนาดใหญ่ที่ซับซ้อนมาก คุณอาจต้องสร้างเมชการชนของคุณเองจากวัตถุขนาดเล็กที่มีความแม่นยำในการชนแบบกล่อง

มนุษย์

Humanoid เป็นคลาสที่ให้ฟังก์ชันการทำงานที่หลากหลายแก่ตัวละครผู้เล่นและตัวละครที่ไม่ใช่ผู้เล่น (NPC) แม้ว่าจะมีพลัง แต่ Humanoid จะมีค่าใช้จ่ายในการคำนวณที่สำคัญ

ปัญหาทั่วไป

  • การเปิดใช้งาน HumanoidStateTypes ทั้งหมดใน NPC - มีค่าใช้จ่ายด้านประสิทธิภาพในการเปิดใช้งาน HumanoidStateTypes บางประเภท ปิดการใช้งานที่ไม่จำเป็นสำหรับ NPC ของคุณ ตัวอย่างเช่น เว้นแต่ NPC ของคุณจะปีนบันไดได้ ก็ปลอดภัยที่จะปิดสถานะ Climbing
  • การสร้าง แก้ไข และสร้างโมเดลใหม่ด้วย Humanoids หรือ MeshParts ที่มีการสกินบ่อยครั้ง
    • สิ่งนี้อาจมีค่าใช้จ่ายสูงสำหรับเอนจินในการประมวลผล โดยเฉพาะอย่างยิ่งหากโมเดลเหล่านี้ใช้ เสื้อผ้าหลายชั้น สิ่งนี้ยังอาจเป็นปัญหาโดยเฉพาะในเกมที่อวตารเกิดใหม่บ่อยครั้ง
    • ใน MicroProfiler แท็ก updateInvalidatedFastClusters ที่ใช้เวลานาน (มากกว่า 4 มิลลิวินาที) มักจะเป็นสัญญาณว่าการสร้าง/แก้ไขอวตารกำลังทำให้เกิดการยกเลิกที่มากเกินไป
  • การใช้ Humanoids ในกรณีที่ไม่จำเป็น - NPC แบบสถิตที่ไม่เคลื่อนที่โดยทั่วไปไม่จำเป็นต้องใช้คลาส Humanoid
  • การเล่นอนิเมชั่นบน NPC จำนวนมากจากเซิร์ฟเวอร์ - อนิเมชั่น NPC ที่ทำงานบนเซิร์ฟเวอร์จำเป็นต้องจำลองบนเซิร์ฟเวอร์และทำซ้ำไปยังลูกค้า สิ่งนี้อาจเป็นภาระที่ไม่จำเป็น
  • การเปลี่ยนขนาดและสเกลที่ไม่จำเป็น - การเปลี่ยนขนาด/สเกลทำให้ FastCluster ต้องสร้างใหม่ พยายามลดสิ่งนี้ในระหว่างการเล่นเกมหากคุณเห็นปัญหาด้านประสิทธิภาพที่เกี่ยวข้องกับ FastCluster นอกจากนี้ การเปลี่ยนแปลงคุณสมบัติอื่น ๆ อาจทำให้ FastCluster ต้องสร้างใหม่ ดังนั้นโดยทั่วไปให้ลดการเปลี่ยนแปลงเหล่านี้ให้น้อยที่สุด

การบรรเทา

  • เล่นอนิเมชั่น NPC บนลูกค้า - ในเกมที่มี NPC จำนวนมาก ให้พิจารณาสร้าง Animator บนลูกค้าและเรียกใช้อนิเมชั่นในท้องถิ่น สิ่งนี้ช่วยลดภาระบนเซิร์ฟเวอร์และความจำเป็นในการทำซ้ำที่ไม่จำเป็น นอกจากนี้ยังทำให้การปรับแต่งเพิ่มเติมเป็นไปได้ (เช่น การเล่นอนิเมชั่นเฉพาะสำหรับ NPC ที่อยู่ใกล้ตัวละคร)
  • ใช้ทางเลือกที่เป็นมิตรกับประสิทธิภาพแทน Humanoids - โมเดล NPC ไม่จำเป็นต้องมีวัตถุ humanoid
    • สำหรับ NPC แบบสถิต ให้ใช้ AnimationController ที่เรียบง่าย เนื่องจากพวกเขาไม่จำเป็นต้องเคลื่อนที่ แต่เพียงแค่ต้องเล่นอนิเมชั่น
    • สำหรับ NPC ที่เคลื่อนที่ ให้พิจารณานำเสนอการควบคุมการเคลื่อนที่ของคุณเองและใช้ AnimationController สำหรับอนิเมชั่น ขึ้นอยู่กับความซับซ้อนของ NPC ของคุณ
  • ปิดการใช้งานสถานะ humanoid ที่ไม่จำเป็น - ใช้ Humanoid:SetStateEnabled() เพื่อเปิดใช้งานเฉพาะสถานะที่จำเป็นสำหรับแต่ละ humanoid
  • จัดกลุ่มโมเดล NPC ที่เกิดใหม่บ่อย - แทนที่จะทำลาย NPC โดยสิ้นเชิง ให้ส่ง NPC ไปยังกลุ่ม NPC ที่ไม่ใช้งาน ด้วยวิธีนี้ เมื่อจำเป็นต้องเกิด NPC ใหม่ คุณสามารถเปิดใช้งาน NPC จากกลุ่มได้ง่าย ๆ กระบวนการนี้เรียกว่าการจัดกลุ่ม ซึ่งช่วยลดจำนวนครั้งที่ต้องสร้างตัวละครใหม่
  • สร้าง NPC เฉพาะเมื่อผู้ใช้อยู่ใกล้ - อย่าสร้าง NPC เมื่อผู้ใช้ไม่ได้อยู่ในระยะ และตัดการเชื่อมต่อเมื่อผู้ใช้ออกจากระยะ
  • หลีกเลี่ยงการเปลี่ยนแปลงในลำดับชั้นของอวตารหลังจากที่มันถูกสร้างขึ้น - การปรับเปลี่ยนบางอย่างในลำดับชั้นของอวตารมีผลกระทบด้านประสิทธิภาพที่สำคัญ มีการปรับแต่งบางอย่างที่มีให้:
    • สำหรับอนิเมชั่นเชิงพาณิชย์ที่กำหนดเอง อย่าอัปเดตคุณสมบัติ JointInstance.C0 และ JointInstance.C1 แทนที่จะอัปเดตคุณสมบัติ Motor6D.Transform
    • หากคุณต้องการแนบวัตถุ BasePart ใด ๆ กับอวตาร ให้ทำเช่นนั้นนอกลำดับชั้นของโมเดลอวตาร

ขอบเขต MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง
stepHumanoidการควบคุมและฟิสิกส์ของ Humanoid
stepAnimationอนิเมชั่นของ Humanoid และ Animator
updateInvalidatedFastClustersเกี่ยวข้องกับการสร้างหรือแก้ไขอวตาร

การเรนเดอร์

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

การเรียกวาด

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

คุณสามารถดูว่ามีการเรียกวาดกี่ครั้งในขณะนี้โดยใช้รายการ Render Stats ⟩ Timing ใน Studio คุณสามารถดู Render Stats ในลูกค้าโดยการกด ShiftF2

ยิ่งมีวัตถุที่ต้องเรนเดอร์ในฉากของคุณในเฟรมที่กำหนดมากเท่าใด การเรียกวาดก็จะยิ่งมากขึ้นเท่านั้น อย่างไรก็ตาม เอนจิน Roblox ใช้กระบวนการที่เรียกว่า instancing เพื่อรวมเมชที่เหมือนกันที่มีลักษณะพื้นผิวเดียวกันเข้าด้วยกันในการเรียกวาดเดียว โดยเฉพาะอย่างยิ่ง เมชหลายตัวที่มี MeshContent เดียวกันจะถูกจัดการในการเรียกวาดเดียวเมื่อ:

ปัญหาอื่น ๆ ที่พบบ่อย

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

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

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

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

    แม้แต่สคริปต์ง่าย ๆ เช่นนี้ก็สามารถช่วยให้คุณระบุส่วนเมชที่มีชื่อเดียวกันซึ่งใช้ ID เมชที่แตกต่างกันได้:

    for _,descendant in workspace:GetDescendants() do
    if descendant:IsA("MeshPart") then
    print(descendant.Name .. ", " .. descendant.MeshId)
    end
    end

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

    LargeRock, rbxassetid://106420009602747 (x144) -- ดี
    LargeRock, rbxassetid://120109824668127
    LargeRock, rbxassetid://134460273008628
    LargeRock, rbxassetid://139288987285823
    LargeRock, rbxassetid://71302144984955
    LargeRock, rbxassetid://90621205713698
    LargeRock, rbxassetid://113160939160788
    LargeRock, rbxassetid://135944592365226 -- อาจเป็นการซ้ำกันทั้งหมด
  • ความซับซ้อนของวัตถุมากเกินไป - แม้ว่าจะไม่สำคัญเท่ากับจำนวนการเรียกวาด แต่จำนวนสามเหลี่ยมในฉากก็มีอิทธิพลต่อระยะเวลาที่ใช้ในการเรนเดอร์เฟรม ฉากที่มีเมชที่ซับซ้อนมากจำนวนมากเป็นปัญหาทั่วไป เช่นเดียวกับฉากที่มีคุณสมบัติ MeshPart.RenderFidelity ตั้งอยู่ที่ Precise บนเมชมากเกินไป

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

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

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

    • วิธีแก้ปัญหาที่มีประสิทธิภาพสูงคือการฝัง Humanoid ไว้ในโมเดล การมี Humanoid จะทำให้พฤติกรรมการจัดกลุ่มเชิงพื้นที่เริ่มต้นถูกแทนที่ โดยบังคับให้ใช้ FastCluster เดียวที่เป็นเอกภาพสำหรับโมเดลทั้งหมด ดังนั้นการอัปเดตตำแหน่งจึงไม่จำเป็นต้องสร้างกลุ่มใหม่ ซึ่งช่วยบรรเทาคอขวดด้านประสิทธิภาพ เทคนิคนี้ควรสงวนไว้สำหรับ MeshParts ที่คาดว่าจะเคลื่อนที่เท่านั้น เนื่องจากอาจทำให้เกิดการใช้หน่วยความจำมากขึ้นและทำให้ประโยชน์ของการปรับแต่งเชิงพื้นที่ลดลง เราขอแนะนำให้คุณทำการวิเคราะห์ประสิทธิภาพเกมของคุณหลังจากทำการเปลี่ยนแปลงประเภทนี้ ดู เคล็ดลับประสิทธิภาพ Humanoid สำหรับข้อมูลเพิ่มเติม
  • จำนวนชิ้นส่วนใน Model มากเกินไป - จำนวนชิ้นส่วนในโมเดลมากเกินไปอาจทำให้เกิดการสร้างใหม่บ่อยขึ้นเนื่องจากความเป็นไปได้ที่คุณสมบัติของชิ้นส่วนจะเปลี่ยนแปลงซึ่งนำไปสู่การสร้างใหม่ทั้งหมด ค้นหาสมดุลที่เหมาะสมของชิ้นส่วนในโมเดลเมื่อใช้ FastCluster

การบรรเทา

  • การสร้างเมชที่เหมือนกันและลดจำนวนเมชที่ไม่ซ้ำกัน - หากคุณมั่นใจว่าเมชที่เหมือนกันทั้งหมดมี ID ของสินทรัพย์พื้นฐานเดียวกัน เอนจินสามารถรับรู้และเรนเดอร์พวกเขาในการเรียกวาดเดียว ตรวจสอบให้แน่ใจว่าได้อัปโหลดเมชแต่ละตัวในแผนที่เพียงครั้งเดียวและจากนั้นทำซ้ำใน Studio เพื่อใช้งานซ้ำ แทนที่จะนำเข้าแผนที่ขนาดใหญ่ทั้งหมดซึ่งอาจทำให้เมชที่เหมือนกันมี ID เนื้อหาที่แยกจากกันและถูกมองว่าเป็นสินทรัพย์ที่ไม่ซ้ำกันโดยเอนจิน Packages เป็นกลไกที่มีประโยชน์สำหรับการใช้งานซ้ำของวัตถุ
  • การตัดการเชื่อมต่อ - การตัดการเชื่อมต่อหมายถึงกระบวนการกำจัดการเรียกวาดสำหรับวัตถุที่ไม่เกี่ยวข้องกับเฟรมที่เรนเดอร์สุดท้าย โดยค่าเริ่มต้น เอนจินจะข้ามการเรียกวาดสำหรับวัตถุที่อยู่นอกมุมมองของกล้อง (frustum culling) และชิ้นส่วน เมช และภูมิประเทศที่ถูกบังจากมุมมองโดยวัตถุอื่น (occlusion culling) ในบางสถานการณ์ เช่น สภาพแวดล้อมในร่ม คุณอาจสามารถใช้ระบบห้องหรือพอร์ทัลและตัดการเชื่อมต่อวัตถุเพื่อช่วยลดการเรียกวาดหรือภาระการคำนวณโดยรวม
  • ลดระดับรายละเอียดสำหรับโมเดล - เปิดใช้งาน instance streaming และตั้งค่าคุณสมบัติ LevelOfDetail ของโมเดลโลกของคุณเป็น SLIM เพื่อเรนเดอร์ เมช SLIM ที่เบาและปรับให้เหมาะสม สำหรับโมเดลเมื่อระยะห่างจากกล้องเพิ่มขึ้น
  • ลดระดับรายละเอียดสำหรับอวตาร - เปิดใช้งานการสตรีมอินสแตนซ์และตั้งค่า Workspace.EnableSLIMAvatars เพื่อเรนเดอร์อวตารแพลตฟอร์มเป็น การแสดงผล SLIM ที่เบาและปรับให้เหมาะสม พร้อมการสนับสนุนการเคลื่อนไหวเต็มรูปแบบเมื่อระยะห่างจากกล้องเพิ่มขึ้น
  • ลดความแม่นยำในการเรนเดอร์ - ตั้งค่า MeshPart.RenderFidelity เป็น Automatic หรือ Performance สิ่งนี้ช่วยให้เมชสามารถกลับไปใช้ทางเลือกที่ซับซ้อนน้อยลง ซึ่งสามารถลดจำนวนโพลิกอนที่ต้องเรนเดอร์
  • ปิดการสร้างเงาบนชิ้นส่วนและวัตถุแสงที่เหมาะสม - เอนจิน Roblox จะลดคุณภาพของเงาโดยอัตโนมัติเมื่อระดับคุณภาพกราฟิกของลูกค้าลดลง ในที่สุดจะปิดการสร้างเงาโดยสิ้นเชิงที่ระดับคุณภาพต่ำกว่า 4 อย่างไรก็ตาม คุณสามารถปิดการสร้างเงาในคุณสมบัติของวัตถุแสงและชิ้นส่วนเพื่อปรับปรุงประสิทธิภาพในขณะที่เปิดใช้งานเงาและเพิ่มโอกาสที่เงาจะยังคงเปิดอยู่ ตัวอย่างบางประการของการปรับแต่งที่คุณสามารถทำได้ทั้งในเวลาตัดต่อหรือแบบไดนามิกในระหว่างการทำงาน:
    • ใช้คุณสมบัติ BasePart.CastShadow เพื่อปิดการสร้างเงาบนชิ้นส่วนเล็ก ๆ ที่ไม่น่าจะมองเห็นเงาได้ กลยุทธ์นี้มีประสิทธิภาพโดยเฉพาะเมื่อใช้กับชิ้นส่วนที่อยู่ห่างไกลจากกล้องของผู้ใช้

    • ปิดเงาบนวัตถุที่เคลื่อนที่เมื่อเป็นไปได้

    • ปิด Light.Shadows บนอินสแตนซ์แสงที่วัตถุไม่จำเป็นต้องสร้างเงา

    • จำกัดระยะและมุมของอินสแตนซ์แสง

    • ใช้อินสแตนซ์แสงน้อยลง

    • พิจารณาปิดไฟที่อยู่นอกช่วงเฉพาะหรือเป็นรายห้องสำหรับสภาพแวดล้อมในร่ม

ขอบเขต MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง
Prepare and Performการเรนเดอร์โดยรวม
Perform/Scene/computeLightingPerformการอัปเดตกริดแสงและเงา
LightGridCPUการอัปเดตกริดแสงแบบวอกเซล
ShadowMapSystemการสร้างแผนที่เงา
Perform/Scene/UpdateViewการเตรียมการสำหรับการเรนเดอร์และการอัปเดตอนุภาค
Perform/Scene/RenderViewการเรนเดอร์และการประมวลผลหลังการเรนเดอร์

การเชื่อมต่อและการทำซ้ำ

การเชื่อมต่อและการทำซ้ำอธิบายกระบวนการที่ข้อมูลถูกส่งระหว่างเซิร์ฟเวอร์และลูกค้าที่เชื่อมต่อ ข้อมูลจะถูกส่งระหว่างลูกค้าและเซิร์ฟเวอร์ในทุกเฟรม แต่ข้อมูลจำนวนมากขึ้นต้องใช้เวลาในการคำนวณมากขึ้น

ปัญหาทั่วไป

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

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

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

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

การบรรเทา

คุณสามารถใช้กลยุทธ์ต่อไปนี้เพื่อลดการทำซ้ำที่ไม่จำเป็น:

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

ขอบเขต MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง
ProcessPacketsการประมวลผลสำหรับแพ็กเกจเครือข่ายที่เข้ามา เช่น การเรียกใช้งานเหตุการณ์และการเปลี่ยนแปลงคุณสมบัติ
Allocate Bandwidth and Run Sendersเหตุการณ์ที่ส่งออกที่เกี่ยวข้องกับเซิร์ฟเวอร์

การใช้หน่วยความจำของสินทรัพย์

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

การสตรีมอินสแตนซ์

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

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

หากการสตรีมอินสแตนซ์เปิดใช้งาน คุณสามารถเพิ่มความก้าวร้าวของมันได้ ตัวอย่างเช่น ให้พิจารณา:

  • ลดการใช้ Enum.ModelStreamingMode.Persistent เท่าที่จะทำได้ คุณอาจต้องอัปเดตสคริปต์ของคุณหากคุณใช้เป็นมาตรการความเข้ากันได้
  • ลด Workspace.StreamingMinRadius และ Workspace.StreamingTargetRadius

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

ปัญหาอื่น ๆ ที่พบบ่อย

  • การทำซ้ำสินทรัพย์ - ข้อผิดพลาดทั่วไปคือการอัปโหลดสินทรัพย์เดียวกันหลายครั้งซึ่งส่งผลให้เกิด ID สินทรัพย์ที่แตกต่างกัน สิ่งนี้อาจทำให้เนื้อหาเดียวกันถูกโหลดเข้าสู่หน่วยความจำหลายครั้ง

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

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

  • พื้นผิวความละเอียดสูง - การใช้หน่วยความจำกราฟิกสำหรับพื้นผิวไม่เกี่ยวข้องกับขนาดของพื้นผิวในดิสก์ จำนวนพิกเซลในพื้นผิวกำหนดการใช้หน่วยความจำ ตัวอย่างเช่น พื้นผิวขนาด 1024x1024 พิกเซลใช้หน่วยความจำกราฟิกมากกว่าพื้นผิวขนาด 512x512 ถึงสี่เท่า

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

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

การบรรเทา

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

  • ค้นหาและแก้ไขสินทรัพย์ที่ซ้ำกัน - มองหาส่วนเมชและพื้นผิวที่เหมือนกันซึ่งถูกอัปโหลดหลายครั้งด้วย ID ที่แตกต่างกัน

    • แม้ว่าจะไม่มี API ในการตรวจจับความคล้ายคลึงของสินทรัพย์โดยอัตโนมัติ แต่คุณสามารถรวบรวม ID สินทรัพย์ภาพทั้งหมดในสถานที่ของคุณ (ไม่ว่าจะด้วยตนเองหรือด้วยสคริปต์) ดาวน์โหลดพวกเขาและเปรียบเทียบโดยใช้เครื่องมือเปรียบเทียบภายนอก
    • สำหรับส่วนเมช กลยุทธ์ที่ดีที่สุดคือการนำ ID เมชที่ไม่ซ้ำกันและจัดระเบียบตามขนาดเพื่อระบุการซ้ำกันด้วยตนเอง
    • แทนที่จะใช้พื้นผิวแยกกันสำหรับสีที่แตกต่างกัน ให้อัปโหลดพื้นผิวเดียวและใช้คุณสมบัติ SurfaceAppearance.Color เพื่อใช้สีต่าง ๆ กับมัน
  • นำเข้าสินทรัพย์ในแผนที่แยกกัน - แทนที่จะนำเข้าแผนที่ทั้งหมดในครั้งเดียว ให้นำเข้าและสร้างสินทรัพย์ในแผนที่แยกกันและสร้างใหม่ พื้นที่นำเข้าไม่ทำการลบซ้ำของเมช ดังนั้นหากคุณนำเข้าแผนที่ขนาดใหญ่ที่มีพื้นผิวแยกกันมากมาย แต่ละพื้นผิวเหล่านั้นจะถูกนำเข้าเป็นสินทรัพย์แยกกัน (แม้ว่าจะเป็นการซ้ำกัน) สิ่งนี้อาจนำไปสู่ปัญหาด้านประสิทธิภาพและหน่วยความจำในอนาคต เนื่องจากแต่ละเมชจะถูกมองว่าเป็นรายบุคคลและใช้หน่วยความจำและการเรียกวาด

  • จำกัดพิกเซลของภาพ ให้อยู่ในจำนวนที่จำเป็นเท่านั้น เว้นแต่ภาพจะใช้พื้นที่ทางกายภาพจำนวนมากบนหน้าจอ มักจะต้องการพิกเซลสูงสุด 512x512 พิกเซล ภาพเล็ก ๆ ส่วนใหญ่ควรมีขนาดเล็กกว่า 256x256 พิกเซล

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

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

เวลาโหลด

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

ปัญหาทั่วไป

  • การสตรีมอินสแตนซ์ปิดใช้งาน - โดยไม่มี การสตรีมอินสแตนซ์ ทั้งหมด Workspace จะต้องทำซ้ำไปยังลูกค้าก่อนที่ผู้เล่นจะสามารถเข้าร่วมได้ ดังนั้นเกมที่มีชิ้นส่วน โมเดล และสินทรัพย์จำนวนมากจึงมีเวลาโหลดที่ยาวนานขึ้นตามสัดส่วน

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

  • เนื้อหา ReplicatedFirst ที่หนัก - ReplicatedFirst จะทำซ้ำก่อนสิ่งอื่นใดและมีอยู่เพื่อถือหน้าจอโหลดที่กำหนดเองเป็นหลัก สินทรัพย์หรือสคริปต์เพิ่มเติมแต่ละรายการในนั้นจะทำให้การเริ่มต้นของเฟสการทำซ้ำหลักล่าช้า

  • การใช้ PreloadAsync() มากเกินไป - เกมหลายเกมใช้หน้าจอโหลดที่กำหนดเองและใช้ ContentProvider:PreloadAsync() เพื่อขอสินทรัพย์เพื่อให้ภาพ เสียง และเมชถูกดาวน์โหลดในพื้นหลัง วิธีการนี้ช่วยให้แน่ใจว่าส่วนสำคัญของเกมของคุณถูกโหลดอย่างเต็มที่โดยไม่มีการปรากฏตัว แต่ข้อผิดพลาดทั่วไปคือการโหลดสินทรัพย์มากกว่าที่จำเป็นจริง ๆ

    ตัวอย่างของแนวทางปฏิบัติที่ไม่ดีคือการโหลด Workspace ทั้งหมด แม้ว่าสิ่งนี้อาจป้องกันการปรากฏตัวของพื้นผิว แต่จะเพิ่มเวลาโหลดอย่างมีนัยสำคัญ

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

  • สคริปต์เริ่มต้นที่มีค่าใช้จ่ายสูง - การดำเนินการสคริปต์ที่หนักใน LocalScripts ที่ทำงานในระหว่างกระบวนการเข้าร่วม เช่น การโหลดโครงสร้างข้อมูลขนาดใหญ่แบบซิงโครนัส จะทำให้การเปลี่ยนจากการทำซ้ำไปสู่สถานะที่เล่นได้ล่าช้า

การบรรเทา

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

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

  • ทำให้ ReplicatedFirst เบา - จำกัด ReplicatedFirst ให้มีเฉพาะสิ่งที่หน้าจอโหลดของคุณต้องการ เช่น องค์ประกอบ UI พื้นฐานแทนที่จะเป็นพื้นผิวขนาดใหญ่หรือโมเดล 3D และหลีกเลี่ยงการคำนวณที่หนักในสคริปต์ที่ทำงานจากมัน สำหรับการสร้างหน้าจอโหลดที่กำหนดเอง รวมถึงเมื่อเรียกใช้ ReplicatedFirst:RemoveDefaultLoadingScreen() โปรดดูที่ หน้าจอโหลด

  • โหลดสินทรัพย์ที่จำเป็นเท่านั้น - ใช้ ContentProvider:PreloadAsync() เฉพาะในสถานการณ์ที่จำเป็น ซึ่งรวมถึง:

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

    หากคุณต้องโหลดสินทรัพย์จำนวนมาก เราขอแนะนำให้คุณจัดเตรียมปุ่ม ข้ามการโหลด

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

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