หน้านี้อธิบายปัญหาประสิทธิภาพทั่วไปและแนวทางปฏิบัติที่ดีที่สุดในการบรรเทาปัญหาเหล่านั้น
การคำนวณสคริปต์
การดำเนินงานที่มีค่าใช้จ่ายสูงในโค้ด 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 วิธีการของ Roblox API หลายรายการที่ถูกเรียกโดยสคริปต์ยังมีแท็ก MicroProfiler ที่เกี่ยวข้องซึ่งสามารถให้ข้อมูลสัญญาณที่มีประโยชน์ได้
การใช้หน่วยความจำของสคริปต์
การรั่วไหลของหน่วยความสามารถเกิดขึ้นเมื่อคุณเขียนสคริปต์ที่ใช้หน่วยความจำที่ตัวจัดการขยะไม่สามารถปล่อยได้อย่างถูกต้องเมื่อไม่ถูกใช้งานอีกต่อไป การรั่วไหลมีความแพร่หลายโดยเฉพาะอย่างยิ่งในฝั่งเซิร์ฟเวอร์ เพราะอาจออนไลน์ติดต่อกันเป็นวันๆ ในขณะที่เซสชันของลูกค้าใช้เวลาสั้นกว่า
ค่าหน่วยความจำด้านล่างใน Developer Console อาจบ่งชี้ถึงปัญหาที่ต้องการการตรวจสอบเพิ่มเติม:
- LuaHeap - การใช้หน่วยความจำที่สูงหรือเพิ่มขึ้นแสดงถึงการรั่วไหลของหน่วยความจำ
- InstanceCount - จำนวนของอินสแตนซ์ที่เพิ่มขึ้นอย่างต่อเนื่องแสดงว่าการอ้างอิงไปยังบางอินสแตนซ์ในโค้ดของคุณไม่ได้ถูกจัดการขยะ
- PlaceScriptMemory - ให้การใช้งานหน่วยความจำทีละสคริปต์
ปัญหาทั่วไป
ปล่อยการเชื่อมต่อที่เชื่อมต่ออยู่ - เอนจิ้นจะไม่จัดการขยะกัดผู้เชื่อมต่อเหตุการณ์ที่เชื่อมต่อกับอินสแตนซ์ใดๆ และค่าที่อ้างถึงภายในฟังก์ชันที่เชื่อมโยงอยู่ ดังนั้นการเชื่อมต่อที่ใช้งานอยู่ของเหตุการณ์และโค้ดภายในอินสแตนซ์ที่เชื่อมโยง, ฟังก์ชันที่เชื่อมโยง, และค่าที่อ้างถึง จะนอกขอบเขตของการจัดการขยะเป็นเวลานาน แม้ว่าฟังก์ชันจะถูกหยุดเมื่ออินสแตนซ์ที่พวกเขาอยู่ถูกทำลาย ข้อผิดพลาดทั่วไปคือต้องสมมติว่าสิ่งนี้ใช้กับวัตถุ Player หลังจากผู้ใช้ออกจากเกม เอนจิ้นจะไม่ทำลายวัตถุ Player ผู้แทนและโมเดลตัวละครของพวกเขาโดยอัตโนมัติ ดังนั้นการเชื่อมต่อกับวัตถุ Player และอินสแตนซ์ภายใต้โมเดลตัวละคร เช่น CharacterAdded จึงยังคงใช้หน่วยความจำถ้าคุณไม่ยกเลิกการเชื่อมต่อในสคริปต์ของคุณ สิ่งนี้อาจส่งผลให้เกิดการรั่วไหลของหน่วยความจำที่สำคัญอย่างมากเมื่อเวลาผ่านไปในฝั่งเซิร์ฟเวอร์เมื่อมีผู้ใช้หลายร้อยคนเข้าร่วมและออกจากเกม
ตาราง - การเพิ่มวัตถุลงในตารางแต่ไม่ลบเมื่อไม่จำเป็นอีกต่อไปทำให้ใช้หน่วยความจำโดยไม่จำเป็น โดยเฉพาะสำหรับตารางที่ติดตามข้อมูลผู้ใช้เมื่อพวกเขาเข้าร่วม ตัวอย่างเช่น โค้ดตัวอย่างดังต่อไปนี้สร้างตารางเพื่อเพิ่มข้อมูลผู้ใช้ทุกครั้งที่ผู้ใช้เข้าร่วม:
ตัวอย่างlocal playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- ข้อมูลบางอย่างend)หากคุณไม่ลบรายการเหล่านี้เมื่อไม่จำเป็นตารางจะยังคงขยายขนาดและใช้หน่วยความจำมากขึ้นเมื่อมีผู้เข้าร่วมมากขึ้น โค้ดใดๆ ที่วนรอบตารางนี้ก็จะมีราคาคำนวณที่สูงขึ้นเมื่อขนาดของตารางเติบโตขึ้น
การบรรเทา
เพื่อทำความสะอาดค่าทั้งหมดที่ใช้เพื่อป้องกันการรั่วไหลของหน่วยความจำ:
ยกเลิกการเชื่อมต่อการเชื่อมต่อทั้งหมด - ตรวจสอบรหัสของคุณและทำให้แน่ใจว่าการเชื่อมต่อต่างๆ ถูกทำความสะอาดผ่านเส้นทางใดเส้นทางหนึ่งต่อไปนี้:
- ยกเลิกการเชื่อมต่อด้วยมือโดยใช้ฟังก์ชัน Disconnect()
- ทำลายอินสแตนซ์ที่เหตุการณ์เป็นของอยู่ด้วยฟังก์ชัน Destroy()
- ทำลายวัตถุสคริปต์ที่การเชื่อมต่อเชื่อมโยงอยู่
ลบวัตถุผู้เล่นและตัวละครหลังจากการออก - เปิดใช้งาน Workspace.PlayerCharacterDestroyBehavior เพื่อทำลายวัตถุผู้เล่นและโมเดลตัวละครโดยอัตโนมัติหลังจากผู้ใช้ออก หากคุณต้องการคุณสามารถทำความสะอาดพวกเขาได้ด้วยตนเอง:
ตัวอย่างการทำความสะอาดผู้เล่นและตัวละคร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 (สี่ครั้งต่อเฟรม) สิ่งนี้ส่งผลให้มีการคำนวณมากขึ้นอย่างมีนัยสำคัญในทุกๆ เฟรม
จำนวนวัตถุจำลองที่ซับซ้อนมากเกินไป - วัตถุสามมิติที่จำลองมากขึ้น เวลาที่ใช้ในการคำนวณฟิสิกส์จะยาวนานยิ่งขึ้นในแต่ละเฟรม บ่อยครั้ง เกมจะมีวัตถุที่ถูกจำลองที่ไม่จำเป็นต้องถูกจำลอง หรือจะมีกลไกที่มีข้อกำหนดและข้อต่อที่มากกว่าที่จะต้องการ
การตรวจจับการชนกันที่แม่นยำเกินไป - ชิ้นส่วนเมซมีคุณสมบัติ CollisionFidelity สำหรับการตรวจจับการชนกันซึ่งมีโหมดต่างๆ ที่มีผลกระทบต่อประสิทธิภาพที่แตกต่างกัน โหมดการตรวจจับการชนกันที่แม่นยำสำหรับชิ้นส่วนเมซมีค่าใช้จ่ายด้านประสิทธิภาพสูงสุดและใช้เวลาในการคำนวณมากขึ้น
การบรรเทา
ยึดชิ้นส่วนที่ไม่ต้องการการจำลอง - ยึดชิ้นส่วนทั้งหมดที่ไม่จำเป็นต้องถูกขับเคลื่อนด้วยฟิสิกส์ เช่น สำหรับ NPC ที่คงที่
ใช้การก้าวฟิสิกส์แบบปรับเปลี่ยน - การก้าวแบบปรับเปลี่ยนจะปรับการคำนวณฟิสิกส์โดยอัตโนมัติสำหรับกลไกฟิสิกส์ ช่วยให้การอัปเดตฟิสิกส์ถูกทำซ้ำได้อย่างน้อยลงในบางกรณี
ลดความซับซ้อนของกลไก
- ตามที่เป็นไปได้ ลดจำนวนข้อกำหนดหรือข้อต่อฟิสิกส์ในกลไก
- ลดจำนวนการชนกันในกลไก เช่น โดยการใช้ขีดจำกัดหรือลิมิตการชนกันเพื่อไม่ให้ส่วนต่างๆ ชนกัน
ลดการใช้ความแม่นยำในการตรวจจับการชนกันของเมซ
สำหรับวัตถุขนาดเล็กหรือไม่สามารถติดต่อได้ ซึ่งผู้ใช้อาจไม่สังเกตเห็นความแตกต่าง ใช้ความแม่นยำของช่อง
สำหรับวัตถุขนาดเล็กถึงขนาดกลาง ใช้ความแม่นยำของช่องหรือช่วง ตามรูปร่าง
สำหรับวัตถุขนาดใหญ่และซับซ้อนมาก สร้างการชนกันเองโดยใช้อินสแตนซ์ที่มองไม่เห็นเมื่อต้องทำ
สำหรับวัตถุที่ไม่ต้องการการชนกัน ปิดการชนกันและใช้ความแม่นยำของช่องหรือช่วง เพราะเรายังเก็บเรขาคณิตการชนกันในหน่วยความจำ
คุณสามารถแสดงเรขาคณิตการชนกันเพื่อการดีบั๊กใน Studio โดยเปิด Collision fidelity จาก Visualization Options ซึ่งอยู่มุมขวาบนของ 3D viewport
นอกจากนี้ คุณยังสามารถใช้ฟิลเตอร์ 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 ไม่จำเป็นต้องมีวัตถุฮิวมานอยด์
- สำหรับ NPC ที่อยู่กับที่ ใช้ AnimationController ที่ง่าย เพราะพวกเขาไม่ต้องเคลื่อนที่ไปมาเพียงแค่เล่นอนิเมชัน
- สำหรับ NPC ที่เคลื่อนที่ให้พิจารณาการทำคอนโทรลเลอร์การเคลื่อนไหวของคุณเองและใช้ AnimationController สำหรับการเล่นอนิเมชัน ขึ้นอยู่กับความซับซ้อนของ NPC ของคุณ
- ปิดสถานะฮิวมานอยด์ที่ไม่ได้ใช้งาน - ใช้ Humanoid:SetStateEnabled() เพื่อเปิดใช้งานเฉพาะสถานะที่จำเป็นสำหรับฮิวมานอยด์แต่ละตัว
- การป้องกันโมเดล NPC ที่เกิดขึ้นบ่อย - แทนที่จะทำลาย NPC อย่างสมบูรณ์ ให้ส่ง NPC ไปยังสระของ NPC ที่ไม่ทำงาน ด้วยวิธีนี้เมื่อจำเป็นต้องมี NPC ใหม่ในการเกิดใหม่ คุณสามารถเปิดใช้งาน NPC ที่มีอยู่จากสระแทน วิธีการนี้เรียกว่า pooling ซึ่งช่วยลดจำนวนครั้งที่จำเป็นต้องสร้างตัวละคร
- เพียงแค่เกิด NPC เมื่อผู้ใช้ใกล้เข้ามา - อย่าสร้าง NPC เมื่อผู้ใช้ไม่ได้อยู่ในขอบเขต และให้ยกเลิก NPC เมื่อผู้ใช้ออกไป
- หลีกเลี่ยงการทำการเปลี่ยนแปลงต่อโครงสร้าง Aavatar หลังจากถูกสร้าง - การดัดแปลงบางอย่างต่อโครงสร้าง Aavatar มีผลกระทบต่อประสิทธิภาพที่สำคัญ โดยมีการปรับปรุงบางอย่างที่มีอยู่:
- สำหรับอนิเมชันทั่วไปที่กำหนดเอง อย่าอัปเดตสถานที่ JointInstance.C0 และ JointInstance.C1 แทนให้ปรับปรุงที่ Motor6D.Transform
ขอบเขตของ MicroProfiler
| ขอบเขต | การคำนวณที่เกี่ยวข้อง |
| stepHumanoid | การควบคุมฮิวมานอยด์และฟิสิกส์ |
| stepAnimation | อนิเมชันฮิวมานอยด์และอนิเมเตอร์ |
| updateInvalidatedFastClusters | ที่เกี่ยวข้องกับการสร้างหรือแก้ไขอวาตาร์ |
การเรนเดอร์
ส่วนสำคัญของเวลาที่ลูกค้าใช้ในแต่ละเฟรมคือการเรนเดอร์ฉากในเฟรมปัจจุบัน เซิร์ฟเวอร์ไม่ทำการเรนเดอร์ ดังนั้นส่วนนี้จึงเฉพาะสำหรับลูกค้า
การเรียกวาด
การเรียกวาดหมายถึงชุดของคำสั่งจากเอนจิ้นไปยัง GPU เพื่อตั้งค่าเรนเดอร์ การเรียกวาดมีค่าใช้จ่ายมากในแง่ของประสิทธิภาพ โดยทั่วไปยิ่งมีการเรียกวาดน้อยต่อเฟรม เวลาที่ใช้ในการเรนเดอร์เฟรมจะน้อยลง
คุณสามารถดูจำนวนการเรียกวาดที่เกิดขึ้นในปัจจุบันได้จากรายการ Render Stats ⟩ Timing ใน Studio คุณสามารถดู Render Stats ในลูกค้าโดยการกด ShiftF2
วัตถุจำนวนมากที่ต้องถูกวาดในฉากของคุณในแต่ละเฟรม จะต้องมีการเรียกวาดมากขึ้น อย่างไรก็ตาม เอนจิ้น Roblox ใช้กระบวนการที่เรียกว่า การแบ่งกลุ่มด้วยแนวทางเดียวกัน เพื่อล้มรวมเมซที่เหมือนกันซึ่งมีลักษณะของเท็กซ์เจอร์เดียวกันเข้าเป็นการเรียกวาดเดียว เมื่อ:
- SurfaceAppearances เหมือนกันถ้ามี หากไม่มีเมื่อ TextureContents เหมือนกัน
- วัสดุเหมือนกันเมื่อทั้ง SurfaceAppearance และ MeshPart.TextureID ไม่มีอยู่
ปัญหาอื่น ๆ ที่พบบ่อย
ความหนาแน่นของวัตถุเกินไป - หากมีวัตถุจำนวนมากทำให้ความหนาแน่นสูง การเรนเดอร์พื้นที่นี้ของฉากจะต้องการการเรียกวาดมากขึ้น หากคุณพบว่าอัตราเฟรมลดลงเมื่อมองไปที่บางส่วนของแผนที่ นี่อาจเป็นสัญญาณที่ดีว่าความหนาแน่นของวัตถุในพื้นที่นี้สูงเกินไป
วัตถุอย่าง decals, textures และ particles ไม่สามารถรวมกลุ่มได้ดีและนำเสนอการเรียกวาดที่เพิ่มขึ้น โดยเฉพาะอย่างยิ่งการเปลี่ยนแปลงคุณสมบัติของ ParticleEmitters สามารถส่งผลกระทบต่อประสิทธิภาพอย่างรุนแรง
พลาดโอกาสในการสร้างกลุ่ม - โดยทั่วไปแล้ว ฉากจะมีเมซเดียวกันซ้ำหลายครั้ง แต่ละสำเนาของเมซมีรหัสทรัพยากรเมซหรือเท็กซ์เจอร์ที่แตกต่างกัน สิ่งนี้จะทำให้ไม่สามารถสร้างกลุ่มได้และส่งผลให้มีการเรียกวาดที่ไม่จำเป็น
สาเหตุทั่วไปของปัญหานี้คือการนำเข้าฉากทั้งหมดในครั้งเดียว แทนที่จะเป็นการนำเข้าสินค้าแต่ละรายการเข้าสู่ Roblox และจากนั้นซ้ำหลังการนำเข้าเพื่อประกอบฉาก
แม้จะมีสคริปต์ง่ายๆ เช่นนี้ก็สามารถช่วยคุณระบุชิ้นส่วนเมซที่มีชื่อเดียวกันที่ใช้รหัสเมซแตกต่างกัน:
for _,descendant in workspace:GetDescendants() doif descendant:IsA("MeshPart") thenprint(descendant.Name .. ", " .. descendant.MeshId)endendผลลัพธ์ (เมื่อเปิดใช้งาน Stack Lines) อาจดูเหมือนอย่างนี้ บรรทัดที่ซ้ำกันแสดงถึงการใช้เมซเดียวกันซึ่งถือว่ายอดเยี่ยม บรรทัดที่ไม่ซ้ำกันไม่ได้แปลว่าจะแย่ แต่นั่นอาจบ่งบอกถึงการมีเมซที่ซ้ำกันในเกมของคุณ ขึ้นอยู่กับการตั้งชื่อของคุณ:
LargeRock, rbxassetid://106420009602747 (x144) -- ดีLargeRock, rbxassetid://120109824668127LargeRock, rbxassetid://134460273008628LargeRock, rbxassetid://139288987285823LargeRock, rbxassetid://71302144984955LargeRock, rbxassetid://90621205713698LargeRock, rbxassetid://113160939160788LargeRock, rbxassetid://135944592365226 -- เป็นระเบิดทั้งหมดความซับซ้อนของวัตถุสูงเกินไป - แม้ว่าจะไม่สำคัญเท่ากับจำนวนการเรียกวาด แต่จำนวนสามเหลี่ยมในฉากจะมีอิทธิพลต่อความยาวที่ต้องใช้เพื่อเรนเดอร์เฟรม ฉากที่มีจำนวนเมซที่ซับซ้อนมากมายและซับซ้อนเป็นปัญหาทั่วไป และยังรวมถึงฉากที่มีคุณสมบัติ MeshPart.RenderFidelity ที่ตั้งไว้ที่ Precise สำหรับเมซมากเกินไป
การสร้างเงามากเกินไป - การจัดการเงาเป็นกระบวนการที่มีค่าใช้จ่ายสูง และแผนที่ที่มีวัตถุแสงที่สร้างเงาจำนวนมากและมีความหนาแน่นสูง (หรือมีส่วนเล็ก ๆ ที่มากเกินไปซึ่งได้รับผลกระทบจากเงา) สามารถประสบปัญหาประสิทธิภาพ
การทับซ้อนของความโปร่งใสที่สูงเกินไป - การวางวัตถุที่มีความโปร่งใสบางส่วนใกล้กันบังคับให้เอนจิ้นเรนเดอร์พิกเซลที่ซ้อนทับหลายครั้ง ซึ่งอาจทำให้เกิดปัญหาเกี่ยวกับประสิทธิภาพ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการระบุและแก้ปัญหานี้ โปรดดูที่ ลบความโปร่งใสที่ซ้อนกัน
การเคลื่อนไหวของ MeshPart ที่มีการสกินมากเกินไป - MeshParts ที่ใช้เป็นส่วนหนึ่งของโมเดล โดยไม่มี Humanoid จะถูกจัดกลุ่มโดยใช้ FastCluster ที่มีการจัดกลุ่มเชิงพื้นที่ เมื่อตราสารเหล่านี้เคลื่อนที่ จะต้องถูกเพิ่มและลบออกตลอดเวลา จากนั้นกลุ่มจะต้องสร้างใหม่ซึ่งส่งผลต่อประสิทธิภาพ
- วิธีที่มีประสิทธิภาพในการดำเนินการคือการฝัง Humanoid ไว้ในโมเดล การมีอยู่ของ Humanoid จะปฏิเสธพฤติกรรมการจัดกลุ่มเชิงพื้นที่เริ่มต้น โดยบังคับให้ใช้ FastCluster เดียวที่เป็นเอกภาพสำหรับโมเดลทั้งหมด ดังนั้นการอัปเดตตำแหน่งจะไม่จำเป็นต้องสร้างกลุ่มใหม่อีกต่อไป ช่วยบรรเทาคอขวดทางด้านประสิทธิภาพ เทคนิคนี้ควรสงวนไว้เฉพาะสำหรับ MeshParts ที่คาดว่าจะเคลื่อนไหว เนื่องจากอาจนำไปสู่เป็นภาระของหน่วยความจำและทำให้ข้อดีของการเพิ่มประสิทธิภาพเชิงพื้นที่ลดลง แนะนำให้คุณจะต้องทดสอบประสิทธิภาพของเกมของคุณหลังจากที่คุณทำการเปลี่ยนแปลงเหล่านี้ โปรดดู เคล็ดลับประสิทธิภาพฮิวมานอยด์ สำหรับข้อมูลเพิ่มเติม
ชิ้นส่วนใน Model มากเกินไป - ชิ้นส่วนในโมเดลมากเกินไปอาจทำให้การสร้างใหม่เกิดขึ้นบ่อยขึ้นโดยเฉพาะอย่างยิ่งเนื่องจากความเป็นไปได้ที่คุณสมบัติของชิ้นส่วนจะเปลี่ยน ทำให้ต้องการการสร้างใหม่แบบเต็มรูปแบบ ค้นหาความสมดุลที่เหมาะสมของชิ้นส่วนในโมเดลเมื่อใช้ FastCluster
การบรรเทา
- การสร้างกลุ่มเมซเดียวกันและลดจำนวนเมซเฉพาะ - หากแน่ใจว่าเมซที่เหมือนกันทั้งหมดมีรหัสทรัพยากรที่อยู่เบื้องหลังเหมือนกัน เอนจิ้นสามารถรับรู้และเรนเดอร์ในแบบการเรียกวาดเดียว ตรวจสอบให้แน่ใจว่าได้อัปโหลดเมซแต่ละเมซในแผนที่เพียงครั้งเดียวและจากนั้นซ้ำใน Studio เพื่อใช้ซ้ำ แทนที่จะนำเข้าฉากที่มีขนาดใหญ่ทั้งหมดซึ่งอาจทำให้เมซที่เหมือนกันมีรหัสเนื้อหาที่แยกออกจากกันและถูกนำไปถือเป็นสินทรัพย์เฉพาะโดยเอนจิ้น แพ็คเกจ เป็นกลไกที่ช่วยในเรื่องการใช้ซ้ำวัตถุ
- การตัดกลุ่ม - การตัดกลุ่มหมายถึงกระบวนการกำจัดการเรียกวาดสำหรับวัตถุที่ไม่เกี่ยวข้องกับเฟรมที่เรนเดอร์ในที่สุด โดยค่าเริ่มต้น เอนจิ้นจะข้ามการเรียกวาดสำหรับวัตถุที่อยู่นอกมุมมองของกล้อง (frustum culling) และชิ้นส่วน, เมซ, และภูมิประเทศที่ไม่สามารถมองเห็นได้จากวัตถุอื่น ๆ (occlusion culling) ในบางสถานการณ์ เช่น สภาพแวดล้อมในบ้าน คุณอาจมีความสามารถในการ implement ระบบห้องหรือพอร์ทัลและทำการตัดกลุ่มวัตถุอย่างมือต่อการลดการเรียกวาดหรือโหลดคอมพิวเตอร์โดยรวม
- ลดระดับรายละเอียดของโมเดล - เปิดใช้งาน instance streaming และตั้งค่า LevelOfDetail ของโมเดลให้เป็น SLIM เพื่อเรนเดอร์ โมเดล SLIM ที่เบาและปรับแต่ง เมื่อระยะห่างจากกล้องเพิ่มขึ้น
- ลดระดับรายละเอียดของอวาตาร์ - เปิดใช้งาน instance streaming และตั้ง 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 ปลั๊กอินใน rigs หากข้อมูลเหล่านี้ไม่ถูกลบออกก่อนที่เกมจะถูกเผยแพร่และโมเดลที่อนิเมทถูกโคลนเป็นประจำ ข้อมูลจำนวนมากจะถูกทำซ้ำอย่างไม่จำเป็น
เซิร์ฟเวอร์ที่ให้บริการ TweenService - หากใช้ TweenService เพื่อทวีตวัตถุต่าง ๆ ในเซิร์ฟเวอร์ คุณสมบัติที่ทวีตจะถูกทำซ้ำในแต่ละลูกค้าในทุกเฟรม สิ่งนี้ไม่เพียงทำให้การทวีตมีปัญหาเมื่อความหน่วงของลูกค้ามีการเปลี่ยนแปลง แต่ยังทำให้มีการขนส่งข้อมูลเครือข่ายที่ไม่จำเป็นด้วย
การบรรเทา
คุณสามารถใช้กลยุทธ์ต่อไปนี้เพื่อลดการทำสำเนาอย่างไม่จำเป็น:
- หลีกเลี่ยงการส่งข้อมูลจำนวนมากในครั้งเดียวผ่านเหตุการณ์ทางไกล แทนที่จะส่งข้อมูลที่จำเป็นเท่านั้นในความถี่ที่ต่ำลง ตัวอย่างเช่น สำหรับสถานะของตัวละคร ให้ทำซ้ำมันเมื่อมีการเปลี่ยนแปลงแทนทุกเฟรม
- แบ่งโครงสร้างอินสแตนซ์ที่ซับซ้อน เช่น แผนที่ และโหลดเป็นชิ้นส่วนเพื่อลดความสามารถในการทำซ้ำบรรทุกงานให้กระจายไปหลาย ๆ เฟรม
- ทำความสะอาดเมตาดาต้าอนิเมชัน โดยเฉพาะไดเรกทอรีอนิเมชันของ rigs หลังจากการนำเข้า
- จำกัดการทำสำเนาอินสแตนซ์ที่ไม่จำเป็น โดยเฉพาะอย่างยิ่งในกรณีที่เซิร์ฟเวอร์ไม่จำเป็นต้องรู้จักกับอินสแตนซ์ที่กำลังถูกสร้าง รวมถึง:
- ผลกระทบภาพ เช่น การระเบิดหรือการยิงเวทย์มนต์ เซิร์ฟเวอร์เพียงแค่จำเป็นต้องรู้ตำแหน่งเพื่อกำหนดผลลัพธ์ ในขณะที่ลูกค้าสามารถสร้างภาพให้เป็นโลคอลได้
- โมเดลมุมมองของรายการในมุมมองบุคคลที่หนึ่ง
- จัดการทวีตบนลูกค้าทั้งหมดแทนที่จะเป็นเซิร์ฟเวอร์
ขอบเขตของ MicroProfiler
| ขอบเขต | การคำนวณที่เกี่ยวข้อง |
| ProcessPackets | การประมวลผลแพ็กเกจเครือข่ายที่เข้ามา เช่น การเรียกเหตุการณ์และการเปลี่ยนแปลงคุณสมบัติ |
| Allocate Bandwidth and Run Senders | เหตุกลางออกของเซิร์ฟเวอร์ |
การใช้หน่วยความจำของทรัพยากร
กลไกที่มีผลกระทบสูงสุดที่ผู้สร้างสามารถใช้เพื่อปรับปรุงการใช้หน่วยความจำของลูกค้า คือการเปิดใช้งาน instance streaming
การทำงานของ instance streaming
Instance streaming โหลดส่วนต่าง ๆ ของโมเดลข้อมูลที่ไม่จำเป็น อย่างมีระเบียบซึ่งอาจช่วยลดเวลาการโหลดและเพิ่มความสามารถของลูกค้าในการป้องกันการล่มเมื่อเกิดแรงดันหน่วยความจำ
หากคุณพบปัญหาเรื่องหน่วยความจำและได้ปิดการใช้งาน instance streaming พิจารณาปรับปรุงเกมของคุณเพื่อรองรับมัน โดยเฉพาะอย่างยิ่งถ้าโลก 3D ของคุณมีขนาดใหญ่ Instance streaming อิงตามระยะทางในพื้นที่ 3D ดังนั้นโลกที่มีขนาดใหญ่จึงได้รับประโยชน์จากมันมากขึ้น
หาก instance streaming เปิดใช้งาน คุณสามารถเพิ่มความเข้มข้นของการทำงานนี้ได้ ตัวอย่างเช่น พิจารณา:
- ลดการใช้ Enum.ModelStreamingMode.Persistent ที่เป็นไปได้ คุณอาจจำเป็นต้องปรับปรุงฟังก์ชันถ้าใช้เป็นมาตรการสำหรับการใช้งานร่วมกัน
- ลด Workspace.StreamingMinRadius และ Workspace.StreamingTargetRadius
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกการสตรีมและประโยชน์ของมัน โปรดดูที่ คุณสมบัติการสตรีม
ปัญหาอื่น ๆ ที่พบบ่อย
การทำสำเนาทรัพยากร - ข้อผิดพลาดทั่วไปคือการอัปโหลดทรัพยากรเดียวกันหลายครั้งทำให้มีรหัสทรัพยากรที่แตกต่างกัน สิ่งนี้อาจทำให้เนื้อเดียวกันถูกโหลดเข้าไปในหน่วยความจำหลายครั้ง
ปริมาณทรัพยากรเกินไป - แม้ว่าทรัพยากรจะไม่เหมือนกัน แต่ก็มีกรณีที่คุณพลาดโอกาสในการใช้ทรัพยากรเดียวกันและประหยัดหน่วยความจำ
ไฟล์เสียง - ไฟล์เสียงอาจเป็นปัจจัยที่คาดไม่ถึงในการใช้หน่วยความจำโดยเฉพาะหากคุณโหลดทั้งหมดในลูกค้าในครั้งเดียวมากกว่าที่จะโหลดเฉพาะสิ่งที่คุณต้องการสำหรับช่วงเกม ในยุทธศาสตร์ โปรดดูที่ เวลาโหลด
เท็กซ์เจอร์ความละเอียดสูง - การใช้หน่วยความจำกราฟิกสำหรับเท็กซ์เจอร์ไม่เกี่ยวข้องกับขนาดของเท็กซ์เจอร์บนดิสก์; จำนวนพิกเซลในเท็กซ์เจอร์จะกำหนดการใช้หน่วยความจำ ตัวอย่างเช่น เท็กซ์เจอร์ขนาด 1024x1024 พิกเซลจะใช้หน่วยความจำกราฟิกมากกว่าสี่เท่าของเท็กซ์เจอร์ขนาด 512x512
รูปภาพที่อัปโหลดไปยัง Roblox จะถูกแปลงเป็นรูปแบบที่กำหนดไว้ ดังนั้นจึงไม่มีประโยชน์ในการอัปโหลดภาพในรูปแบบสีที่เกี่ยวข้องกับจำนวนไบต์ต่อพิกเซลที่น้อยกว่า นอกจากนี้ การบีบอัดภาพก่อนการอัปโหลดหรือการลบช่องอัลฟาจากภาพที่ไม่ต้องการสามารถลดขนาดของภาพบนดิสก์ แต่ไม่ปรับปรุงการใช้งานหน่วยความจำ
เมื่อเกมโหลด เอนจิ้นจะเริ่มด้วยคุณภาพที่ต่ำกว่าของเท็กซ์เจอร์และจากนั้นเพิ่มคุณภาพขึ้นอยู่กับหน่วยความจำของอุปกรณ์ที่มีอยู่, ระยะห่างจากกล้อง, จำนวนพื้นที่จอภาพที่เท็กซ์เจอร์ใช้ขึ้นไป, และปัจจัยอื่น ๆ แม้ว่าจะเช่นนั้น การจัดการขนาดของเท็กซ์เจอร์ของคุณทางยุทธศาสตร์จะช่วยปรับปรุงการใช้หน่วยความจำในเกมของคุณ
การบรรเทา
อัปโหลดทรัพยากรเพียงครั้งเดียว - ใช้รหัสทรัพยากรเดียวกันซ้ำในวัตถุและตรวจสอบให้แน่ใจว่าทรัพยากรเดียวกัน โดยเฉพาะเมซและภาพ จะไม่ได้อัปโหลดแยกกันหลายครั้ง
ค้นหาและแก้ไขทรัพยากรที่ซ้ำกัน - มองหาชิ้นส่วนเมซและเท็กซ์เจอร์ที่เหมือนกันซึ่งถูกอัปโหลดหลายครั้งพร้อมรหัสที่แตกต่างกัน
- แม้จะไม่มี API ที่ตรวจจับความคล้ายคลึงกันของทรัพยากรโดยอัตโนมัติ แต่คุณสามารถเก็บรวบรวมรหัสทรัพยากรภาพทั้งหมดในสถานที่ของคุณ (ทั้งแบบแมนนวลหรือด้วยสคริปต์), ดาวน์โหลดพวกเขา, และเปรียบเทียบโดยใช้เครื่องมือการเปรียบเทียบภายนอก
- สำหรับชิ้นส่วนเมซ กลยุทธ์ที่ดีที่สุดคือการนำรหัสเมซที่ไม่ซ้ำกันและจัดระเบียบตามขนาดเพื่อระบุการซ้ำที่ไม่ต้องการ
- แทนที่จะใช้เท็กซ์เจอร์ที่แยกกันสำหรับสีที่ต่างกัน ให้อัปโหลดเท็กซ์เจอร์เดียวและใช้คุณสมบัติ SurfaceAppearance.Color เพื่อใช้ลูกเล่นต่าง ๆ
นำเข้าทรัพยากรในแผนที่แยกกัน - แทนที่จะนำเข้าแผนที่ทั้งหมดในครั้งเดียว ให้ทำการนำเข้าสินค้าและประกอบในแผนที่โดยแยกกัน เครื่องมือการนำเข้าไม่ได้ทำการลบข้อมูลซ้ำหากมีการใช้งานเมซจำนวนมากและหากการนำเข้าแผนที่ขนาดใหญ่โดยมีแผ่นพื้นไม่มีที่สิ้นสุดหลายแผ่น เมซแต่ละชิ้นจะถูกนำเข้าเป็นทรัพยากรแยกจากกัน (แม้ว่าจะอยู่ในรูปที่ซ้ำกัน) สิ่งนี้อาจทำให้เกิดปัญหาเรื่องประสิทธิภาพและหน่วยความจำในอนาคต เนื่องจากทุกๆ เมซจะถูกนำมาปฏิบัติอย่างอิสระและใช้หน่วยความจำและการเรียกวาดไปด้วย
จำกัดพิกเซลของภาพ ให้อยู่ในจำนวนที่จำเป็น ไม่เกินกว่านั้น หากไม่ได้อัปโหลดภาพซึ่งใช้พื้นที่มากทางกายภาพบนหน้าจอ โดยทั่วไปใช้เพียงไม่เกิน 512x512 พิกเซล รูปภาพเล็กๆ ส่วนใหญ่ควรมีขนาดเล็กกว่าหรือเท่ากับ 256x256 พิกเซล
ใช้แผ่นตัด เพื่อที่จะให้การใช้หน่วยความจำสูงสุดมีการใช้เท็กซ์เจอร์ใหม่ในแผนที่ 3D สำหรับขั้นตอนและตัวอย่างเกี่ยวกับการสร้างแผ่นตัด โปรดดูที่ สร้างแผ่นตัด
นอกจากนี้ คุณยังสามารถพิจารณาใช้สไปรท์ชีทเพื่อโหลดภาพ UI ขนาดเล็กหลายภาพในรูปภาพเดียว จากนั้นคุณสามารถใช้ ImageLabel.ImageRectOffset และ ImageLabel.ImageRectSize เพื่อแสดงชิ้นส่วนของแผ่น
เวลาโหลด
เกมจำนวนมากจะใช้หน้าจอโหลดที่กำหนดเองและใช้เมธอด ContentProvider:PreloadAsync() เพื่อขอทรัพยากร เพื่อให้ภาพ, เสียง, และเมซถูกดาวน์โหลดในพื้นหลัง
ข้อดีของวิธีการนี้คือช่วยให้คุณมั่นใจว่าชิ้นส่วนสำคัญของเกมโหลดได้อย่างเต็มที่โดยไม่มีการข้าม อย่างไรก็ตาม ข้อผิดพลาดทั่วไปคือการใช้วิธีการนี้มากเกินไปเพื่อโหลดทรัพยากรมากกว่าที่ต้องการจริง ๆ
ตัวอย่างของแนวปฏิบัติที่ไม่ดีคือการโหลดทั้ง Workspace แม้ว่านี่จะช่วยป้องกันการข้ามเท็กซ์เจอร์ แต่มันจะทำให้เวลาการโหลดสูงขึ้นอย่างมาก
อีกหนึ่งแนวปฏิบัติที่คล้ายกันคือการใช้ ContentProvider.RequestQueueSize เพื่อให้แน่ใจว่าทรัพยากรที่ร้องขอทั้งหมดเสร็จสิ้นการโหลด อย่างไรก็ตาม วิธีนี้มีปัญหาเดียวกัน นั่นคือเวลาการโหลดสูงขึ้นอย่างมาก ขณะเดียวกันก็เป็นวิธีการที่ไม่น่าเชื่อถือเนื่องจากลักษณะที่เปลี่ยนแปลงของมัน
แทนที่จะทำเช่นนั้นให้ใช้ ContentProvider:PreloadAsync() ในกรณีที่จำเป็น ซึ่งรวมถึง:
- รูปภาพในหน้าจอโหลด
- รูปภาพที่สำคัญในเมนูเกมของคุณ เช่น ภาพพื้นหลังของปุ่มและไอคอน
- ทรัพยากรที่สำคัญในพื้นที่เริ่มต้นหรือพื้นที่การเกิด
หากคุณต้องโหลดทรัพยากรจำนวนมาก เราแนะนำให้คุณจัดให้มีปุ่ม ข้ามการโหลด