เพิ่มประสิทธิภาพ

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

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

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

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

ปัญหาทั่วไป

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

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

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

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

ขอบเขตของ MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง

RunService.PreRender (การดำเนินการก่อนที่จะเรนเดอร์)

รหัสที่ดำเนินการในอีเวนต์ PreRender

RunService.PreSimulation สามารถใช้งานได้แล้ว

การดําเนินโค้ดบนอีเวนต์ Stepped
ทำงานบริการ RunService.PostSimulationรหัสดำเนินการในอีเวนต์ Heartbeat
การดำเนินการ RunService.Heartbeatรหัสดำเนินการในอีเวนต์ Heartbeat

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

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

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

ค่าหน่วยความจําต่อไปนี้ใน คอนโซลผู้พัฒนา สามารถบ่งบอกถึงปัญหาที่ต้องการการตรวจสอบเพิ่มเติม:

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

ปัญหาทั่วไป

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

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

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

    ตัวอย่างเช่น

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

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

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

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

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

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

    ตัวอย่างเช่น

    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)

การคำนวณทางกายภาพ

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

ปัญหาทั่วไป

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

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

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

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

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

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

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

  • ลดความซับซ้อนของเครื่องกล * หากเป็นไปได้ให้ลดจํานวนข้อจํากัดทางฟิสิกส์หรือข้อต่อในการประกอบให้น้อยที่สุด

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

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

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

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

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

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

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

ขอบเขตของ MicroProfiler

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

การใช้หน่วยความจําทางกายภาพ

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

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

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

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

วิธีลดความเสี่ยง

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

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

มนุษย์เทียม

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

ปัญหาทั่วไป

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

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

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

ขอบเขตของ MicroProfiler

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

การทำเรนเดอร์

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

เรียกภาพ

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

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

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

ปัญหาทั่วไปอื่น ๆ

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

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

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

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

  • ความซับซ้อนของวัตถุมากเกินไป - แม้ว่าจะไม่สำคัญเท่ากับจํานวนการเรียกวาด แต่จํานวนสามเหลี่ยมในฉากก็มีอิทธิพลต่อระยะเวลาที่ใช้ในการแสดงผลของเฟรมฉากที่มีจํานวนเมชที่ซับซ้อนมากจํานวนมากเป็นปัญหาทั่วไปเช่นเดียวกับฉากที่มีค่า MeshPart.RenderFidelity ของคุณตั้งค่าเป็น Enum.RenderFidelity.Precise บนเมชที่มากเกินไป

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

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

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

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

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

    • ปิดการใช้งาน Light.Shadows บนตัวอย่างแสงที่วัตถุไม่จำเป็นต้องโค้งเงา

    • จำกัดระยะและมุมของตัวอย่างแสง

    • ใช้แสงน้อยลง

ขอบเขตของ MicroProfiler

ขอบเขตการคำนวณที่เกี่ยวข้อง
เตรียมและดำเนินการการแสดงผลโดยรวม
ดําเนินการ/ฉาก/คํานวณแสงดําเนินการอัปเดตกริดแสงและเงา
หน่วยประมวลผล LightGridCPUการอัปเดตเครือข่ายแสง Voxel
ระบบ ShadowMapแผนที่เงา
ดำเนินการ/ฉาก/อัปเดตมุมมองการเตรียมพร้อมสําหรับการเรนเดอร์และการอัปเดตอนุภาค
ดำเนินการ/ฉาก/RenderViewการเรนเดอร์และการประมวลผลภายหลัง

การเชื่อมต่อและการจำลอง

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

ปัญหาทั่วไป

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

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

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

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

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

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

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

ขอบเขตของ MicroProfiler

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

การใช้หน่วยความจําทรัพยากรอย่างเต็มที่

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

การสตรีมตัวอย่างอินสแตนซ์

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

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

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

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

ปัญหาทั่วไปอื่น ๆ

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

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

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

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

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

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

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

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

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

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