วนรอบเกม“ ดีที่สุด” สำหรับ 2D-scroller


14

เป็นไปได้หรือไม่ที่จะอธิบายโครงร่าง "ดีที่สุด" (ในแง่ของประสิทธิภาพ) สำหรับลูปเกมของผู้เลื่อนด้าน 2D ในบริบทนี้ "game loop" ใช้การป้อนข้อมูลของผู้ใช้อัปเดตสถานะของวัตถุเกมและดึงวัตถุเกม

ตัวอย่างเช่นการมีคลาสฐาน GameObject ที่มีลำดับชั้นการสืบทอดลึกอาจดีสำหรับการบำรุงรักษา ... คุณสามารถทำสิ่งต่อไปนี้:

foreach(GameObject g in gameObjects) g.update();

อย่างไรก็ตามฉันคิดว่าวิธีนี้สามารถสร้างปัญหาด้านประสิทธิภาพได้

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

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


คำตอบ:


45

ตัวอย่างเช่นการมีคลาสฐาน GameObject ที่มีลำดับชั้นการสืบทอดลึกอาจดีสำหรับการบำรุงรักษา ...

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

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

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

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

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

ระบบดังกล่าวมักจะถูกแยกออกอย่างมากซึ่งเป็นประโยชน์ต่อการบำรุงรักษาเช่นกัน

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

ผลวิธีการที่ดีที่สุดในการวนลูปเกมคือแทนที่จะเป็นแบบดั้งเดิมของคุณ

foreach(GameObject g in gameObjects) g.update();

บางสิ่งบางอย่างเช่น

ProcessUserInput();
UpdatePhysicsForAllObjects();
UpdateScriptsForAllObjects();
UpdateRenderDataForAllObjects();
RenderEverything();

เช่นในโลกแต่ละGameObjectอาจจะมีตัวชี้หรืออ้างอิงถึงตัวของมันเองPhysicsDataหรือScriptหรือRenderDataสำหรับกรณีที่คุณอาจจำเป็นต้องมีปฏิสัมพันธ์กับวัตถุบนพื้นฐานของแต่ละบุคคล แต่ที่เกิดขึ้นจริงPhysicsData, Scripts, RenderDataและอื่น ๆ ทุกคนจะได้เป็นเจ้าของโดยระบบย่อยของตน (ตัวจำลองฟิสิกส์, สภาพแวดล้อมการโฮสต์สคริปต์, ตัวแสดงผล) และประมวลผลเป็นกลุ่มตามที่ระบุไว้ข้างต้น

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

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


5
ท่านลอร์ดดีนี่เป็นคำตอบที่ดี
Raveline

2

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

เป็นตัวอย่าง ... สมมติว่าคุณเริ่มสร้างฐานเกมวัตถุที่มีคุณสมบัติขั้นต่ำว่าตำแหน่ง (สำหรับ x และ y), displayObject (นี่หมายถึงภาพถ้าองค์ประกอบการวาดภาพของมัน) ความกว้างความสูง ฯลฯ ...

ตอนนี้ถ้าเราจำเป็นต้องเพิ่มคลาสย่อยซึ่งจะมีสถานะภาพเคลื่อนไหวคุณอาจย้าย 'รหัสควบคุมภาพเคลื่อนไหว' (พูด currentAnimationId, จำนวนเฟรมสำหรับภาพเคลื่อนไหวนี้และอื่น ๆ ) ไปยัง GameObjectBase ด้วยความคิดที่ว่า วัตถุจะมีภาพเคลื่อนไหว
ในภายหลังหากคุณต้องการเพิ่มเนื้อหาที่แข็งแกร่งซึ่งเป็นแบบสแตติก (ไม่มีภาพเคลื่อนไหวใด ๆ ) คุณต้องตรวจสอบ 'รหัสควบคุมภาพเคลื่อนไหว' ในฟังก์ชั่นอัพเดทของ GameObject Base (แม้ว่าจะเป็นการตรวจสอบว่ามีภาพเคลื่อนไหวอยู่หรือไม่ก็ตาม) .. มันสำคัญ!) ตรงกันข้ามกับสิ่งนี้หากคุณทำตามโครงสร้างพื้นฐานของ Component คุณจะมี 'Animation Control Component' ติดอยู่กับวัตถุของคุณหากจำเป็นคุณจะต้องแนบมันไว้สำหรับร่างกายแบบคงที่คุณจะไม่ติดส่วนประกอบนั้น วิธีเราสามารถหลีกเลี่ยงการตรวจสอบที่ไม่จำเป็น

ดังนั้นการเลือกรูปแบบขึ้นอยู่กับขนาดของโครงการโครงสร้าง GameObject เป็นหลักง่าย ๆ สำหรับโครงการขนาดเล็กความหวังนี้ช่วยได้เล็กน้อย


@Josh Petrie - คำตอบที่ยอดเยี่ยมจริงๆ!
Ayyappa

@Josh Petrie - คำตอบที่ดีจริงๆพร้อมลิงก์ที่มีประโยชน์! (sry ไม่ทราบวิธีการวางความคิดเห็นนี้ถัดจากโพสต์ของคุณ: P)
Ayyappa

คุณสามารถคลิกลิงก์ "เพิ่มความคิดเห็น" ใต้คำตอบของฉันตามปกติ แต่ต้องใช้ชื่อเสียงมากกว่าที่คุณมีอยู่ในปัจจุบัน (ดูgamedev.stackexchange.com/privileges/comment ) และขอบคุณ!
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.