ฉันจะลดผลกระทบด้านประสิทธิภาพของการแสดงผลต้นไม้ได้อย่างไร


24

ฉันกำลังทำเกมโพลีสุกใสต่ำ ฉันมีภูมิประเทศที่มีน้ำและฉันต้องการต้นไม้มากมาย ฉันมีต้นไม้จำนวน 10,000 ต้นในขณะนี้ ต้นไม้แต่ละต้นมีรูปสามเหลี่ยมไม่เกิน 200 รูปดังนั้นพวกเขาจึงไม่เก็บภาษีมากเกินไป

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

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

ฉันจะทำอย่างไรเพื่อให้เกมของฉันทำงานเร็วขึ้นด้วยต้นไม้มากขึ้น


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

ต้นไม้กำลังวาดรูปให้คุณมองออกไปนอกหน้าต่างซึ่งจะทำให้ประสิทธิภาพการทำงานลดลง
mbomb007

คุณได้ลองใช้งาน profiler แล้วหรือยัง? ถ้าเป็นเช่นนั้นคอขวดอยู่ที่ไหน?
Mikael Högström

คุณกำลังทำเฟลิคัมการคัดเลือกหรือไม่?
Krythic

การเลือกสรร frustum คืออะไร?
นายแมตต์

คำตอบ:


43

มีสองสิ่งที่คุณสามารถทำได้เพื่อเพิ่มประสิทธิภาพการวาด

  1. คุณบอกว่าพวกเขาค่อนข้างไกล คุณสามารถใช้LODเพื่อลดจำนวนจุดยอดของต้นไม้เหล่านั้นและลดเวลาที่ต้องใช้ในการผ่านจุดยอดทั้งหมดที่ถูกวาด แม้ว่านี่จะไม่ใช่ปัญหาในมือ (GTX1080 ที่มีต้นเพียง 10k ต้นที่มี 200 ต้นต่อต้น แต่ยังมีตัวเลขที่อ่อนแอสำหรับ GPU) ฉันยังคงรวมมันไว้ Billboarding เป็นเครื่องมือที่มีประสิทธิภาพสำหรับระดับ LOD ที่ต่ำที่สุดเนื่องจากเป็นระนาบพื้นราบที่หันหน้าเข้าหากล้องพร้อมกับภาพต้นไม้ที่อยู่ในนั้น มันเสียความรู้สึกลึกซึ่งเป็นสาเหตุที่ดีสำหรับระดับต่ำสุดเนื่องจากผู้เล่นส่วนใหญ่จะไม่สังเกตเห็นความแตกต่าง

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

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

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

    ในการทำให้เครื่องยนต์สร้างการเรนเดอร์แบบแบตช์ที่ดีขึ้นคุณอาจต้องการจัดกลุ่มตาข่ายเดียวกันเข้าด้วยกันในฉาก การเล่นด้วยคิวการเรนเดอร์วัสดุจะให้ผลลัพธ์ที่ดีหากตาข่ายหนึ่งมีวัสดุเดียวกันเสมอ ในระหว่างการพัฒนาเกมมือถือที่ฉันกำลังทำงานอยู่ฉันใช้มันเพื่อลด drawcalls มากกว่าครึ่งในฉากทดสอบของฉัน นอกจากนี้เนื่องจาก Unity 5.6 ตรวจสอบให้แน่ใจว่าคุณได้Enable Instancingทำเครื่องหมายในเนื้อหา

  5. รักษา drawcalls และ SetPass ของคุณให้เรียกใช้โดยทั่วไป สิ่งเหล่านี้เป็นการเรียกร้องให้ GPU ของคุณวาดสิ่งต่างๆและมีค่าใช้จ่ายสูง การลด drawcalls (ซึ่งเป็นสิ่งที่การแบตช์และอินสแตนซ์กำลังทำอยู่) จะเพิ่มประสิทธิภาพโดยรวมที่ CPU ของคุณสามารถให้ได้ตามที่ต้องการเพื่อรอให้น้อยลง การเรียกใช้ SetPass เป็นการเปลี่ยนแปลงของเฉดสีในปัจจุบันของคุณดังนั้นหากคุณมีวัสดุที่แตกต่างกันจำนวนมากคุณจะมีการเรียกใช้ SetPass หลายครั้งซึ่งทำให้ CPU ต้องรอสักครู่

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

  7. หากฉากของคุณมีขนาดใหญ่และเวลา CPU ของคุณยังคงเป็นส่วนใหญ่ใน Unity ที่เดินผ่านฉากต้นไม้เพื่อสร้างรายการเพื่อแสดงวัตถุทั้งหมดสิ่งหนึ่งที่คุณสามารถทำได้คือไม่ให้ Unity จัดการกับการเรนเดอร์ หากคุณมีวิธีที่ดีกว่าในการติดตามวัตถุที่วาดได้คุณสามารถใช้CommandBuffer.DrawMeshInstancedหรือGraphics.DrawMeshInstancedเพื่อวาดวัตถุเหล่านั้นด้วยมือ ฉันจะไม่ลงรายละเอียดมากนักเกี่ยวกับเรื่องนี้เพราะมันล้ำหน้ากว่ามากและเกี่ยวข้องกับการเลือกสรรการตรวจสอบตัวเองและอะไรก็ตาม

ในกรณีถ้าแบบคงที่หรือแบบไดนามิก batching ทำงานไม่ถูกต้อง (ซึ่งคุณสามารถมองเห็นโดยการตรวจสอบดีบักกรอบ), meshRenderer.materialคุณต้องให้แน่ใจว่าคุณได้แน่นอนโดยใช้วัสดุที่ใช้ร่วมกันและไม่ได้มีการทำสำเนาของวัสดุโดยอุบัติเหตุที่มีการเรียก การโทร.materialจะทำสำเนาของวัสดุของคุณและแบ่งแบทช์ ใช้.sharedMaterialแทน

เนื่องจาก Unity 5.6 คุณสามารถใช้ Frame Debugger เพื่อกำหนดสาเหตุที่ drawcall บางตัวไม่ได้แบตช์กับ drawcalls ก่อนหน้า สิ่งนี้จะมีประโยชน์มากในขณะที่พยายามลด drawcalls ในเกมของคุณ

การย้ายอินสแตนซ์มีข้อดีดังต่อไปนี้มากกว่าการแบทช์คงที่ / ไดนามิก / กำหนดเอง:

  • ใช้หน่วยความจำน้อยลงเนื่องจากไม่จำเป็นต้องใช้ตาข่ายในการทำซ้ำ
  • สามารถใช้วัสดุหลายรายการต้องใช้ shader ร่วมกันเท่านั้น
  • วัตถุสามารถเคลื่อนไหวได้

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


1. ใช่ฉันลอง LOD แล้วและทำให้ฉันประหลาดใจมากมันทำให้แย่ลง ฉันมีต้นไม้ 3 แบบแต่ละต้นมีจุดสุดยอดที่ต่ำกว่าเล็กน้อยและระนาบแบนหนึ่งที่มีภาพที่แสดงต้นไม้บนนั้น
นายแมตต์

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

3. สิ่งนี้จะปรับปรุงประสิทธิภาพแบบใดจริง ๆ มันคุ้มค่าที่จะลอง?
นายแมตต์

1
2/3: จากประสบการณ์ของฉัน Unity ทำงานได้ไม่ดีมากที่การสร้างแบตช์แบบไดนามิกและการสร้างแบตช์แบบคงที่เพิ่มขนาดของบิวด์ดังนั้นฉันจึงนำแบตช์ไปใช้ด้วยตัวเอง การใช้เทคนิคนี้ทำให้ฉันสามารถสร้าง 2,500 drawcall เพื่อบีบอัดเป็น 300 drawcalls ซึ่งเป็นสิ่งสำคัญสำหรับเกมมือถือของเราที่ drawcalls มีความสำคัญ มันทำการคำนวณจุดยอดเยี่ยมเล็กน้อย (นอกจอ) เล็กน้อย แต่มันก็คุ้มค่า
Lasse

2
tfw เมื่อคุณอ่านคำถามเกี่ยวกับประสิทธิภาพที่ไม่ดีกับต้นไม้และไม่มีคำเดียวเกี่ยวกับป้ายโฆษณาหายไป
Num Lock

13

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

หากยังมีอะไรอีกบ้างที่ฉันสามารถทำเพื่อปรับปรุงการแสดงได้โปรดแจ้งให้เราทราบฉันจะขอบคุณมากที่สุด!


2
ใช้ Occlusion Culling เช่นกันถ้าฉากของคุณใหญ่ลองพิจารณาแบ่งเป็นชิ้น ๆ ตัวอย่างเช่นภูมิประเทศจำนวนมากและโหลดและยกเลิกการโหลด
Candid Moon _Max_

เนื่องจากคุณดูเหมือนจะแก้ไขปัญหาของคุณได้แล้วคุณควรยอมรับคำตอบนี้
Gnemlock
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.