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

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

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

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

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

ปัญหาทั่วไป

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

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

การลดผลกระทบ

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

ขอบเขตของ 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 (สี่ครั้งต่อเฟรม) ซึ่งส่งผลให้การคำนวณใช้เวลามากขึ้นในแต่ละเฟรม

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

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

การลดผลกระทบ

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

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

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

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

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

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

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

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

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

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

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

ขอบเขตของ MicroProfiler

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

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

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

ปัญหาทั่วไป

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

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

วิธีการลดผลกระทบ

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

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

มนุษย์

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

ปัญหาทั่วไป

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

การลดผลกระทบ

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

ขอบเขตของ MicroProfiler

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

การเรนเดอร์

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

การเรียกวาด

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

คุณสามารถดูว่ามีกี่ครั้งที่มีการเรียกวาดเกิดขึ้นในขณะที่รายการ Render StatsTiming ใน Studio คุณสามารถดู Render Stats ในไคลเอนต์โดยการกด ShiftF2

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

ปัญหาอื่น ๆ

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

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

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

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

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


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

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


    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 มากเกินไป

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

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

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

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

การลดผลกระทบ

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

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

  • การลดระดับความละเอียดของโมเดล - เปิดใช้งาน instance streaming และตั้งค่า LevelOfDetail ของโมเดลในโลกของคุณเป็น SLIM เพื่อเรนเดอร์ optimized lightweight SLIM meshes ให้กับโมเดลเมื่อระยะห่างจากกล้องเพิ่มขึ้น

  • การลดระดับความละเอียดของตัวอวตาร - เปิดใช้งานการสตรีมประจำและตั้งค่า Workspace.EnableSLIMAvatars เพื่อเรนเดอร์โมเดลตัวอวตารของแพลตฟอร์มที่มีจำนวนอุปกรณ์เสริมหรือชั้นของเสื้อผ้าเป็น optimizing lightweight avatar representations พร้อมการสนับสนุนเต็มรูปแบบสำหรับอนิเมชันเมื่อห่างจากกล้องมากขึ้น

  • การลดความละเอียดในการเรนเดอร์ - ตั้งค่า MeshPart.RenderFidelity เป็น Automatic หรือ Performance วิธีนี้ช่วยให้ meshes สามารถย้อนกลับไปสู่ตัวเลือกที่ซับซ้อนน้อยลง ซึ่งสามารถลดจำนวนโพลิกอนที่ต้องเรนเดอร์ให้ลดลง

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

    • ใช้คุณสมบัติ BasePart.CastShadow เพื่อปิดการสร้างเงาที่ชิ้นส่วนขนาดเล็กที่เงาไม่ค่อยชัดเจน วิธีนี้มีประสิทธิภาพโดยเฉพาะเมื่อใช้กับชิ้นส่วนที่อยู่ไกลจากกล้องของผู้ใช้

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

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

    • จำกัดระยะและมุมของ instance ของแสง

    • ใช้การดำเนินการของแสงน้อยลง

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

ขอบเขตของ MicroProfiler

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

เครือข่ายและการทำสำเนา

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

ปัญหาทั่วไป

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

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

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

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

การลดผลกระทบ

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

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

ขอบเขตของ MicroProfiler

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

การลดผลกระทบ

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

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

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

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

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

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

เวลาในการโหลด

เกมหลายเกมมีหน้าจอโหลดแบบกำหนดเองและใช้วิธีการ ContentProvider:PreloadAsync() เพื่อขอทรัพย์สินเพื่อให้ภาพ เสียง และ mesh ได้ถูกดาวน์โหลดในพื้นหลัง

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

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

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

แทนที่จะทำเช่นนี้ ให้ใช้ ContentProvider:PreloadAsync() ในกรณีที่จำเป็นซึ่งรวมถึง:

  • รูปภาพในหน้าจอโหลด
  • รูปภาพสำคัญในเมนูเกมของคุณ เช่น พื้นหลังของปุ่มและไอคอน
  • ทรัพย์สินที่สำคัญในพื้นที่เริ่มต้นหรือตั้งแต่ต้น
©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ