ฉันอยู่ในเส้นทางที่ถูกต้องด้วยสถาปัตยกรรมองค์ประกอบนี้หรือไม่?


9

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

ก่อนหน้านี้ฉันมีลำดับขั้นที่ทำสิ่งนี้:

Item -> Equipment -> Weapon
                  -> Armor
                  -> Accessory
     -> SyntehsisItem
     -> BattleUseItem -> HealingItem
                      -> ThrowingItem -> ThrowsAsAttackItem

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

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

นี่คือสิ่งที่ฉันกำลังคิดสำหรับการตั้งค่าส่วนประกอบ:

ฉันมีคลาสไอเท็มพื้นฐานที่มีสล็อตสำหรับส่วนประกอบต่าง ๆ (เช่นสล็อตคอมโพเนนต์อุปกรณ์สล็อตคอมโพเนนต์การแพทย์ ฯลฯ รวมถึงแผนที่สำหรับคอมโพเนนต์โดยพลการ) ดังนั้นสิ่งนี้:

class Item
{
    //Basic item properties (name, ID, etc.) excluded
    EquipmentComponent* equipmentComponent;
    HealingComponent* healingComponent;
    SynthesisComponent* synthesisComponent;
    ThrowComponent* throwComponent;
    boost::unordered_map<std::string, std::pair<bool, ItemComponent*> > AdditionalComponents;
} 

ส่วนประกอบรายการทั้งหมดจะสืบทอดมาจากคลาส ItemComponent พื้นฐานและแต่ละประเภทส่วนประกอบมีหน้าที่รับผิดชอบในการบอกเอ็นจิ้นถึงวิธีการใช้ฟังก์ชันการทำงานนั้น เช่น HealingComponent บอกกลไกการต่อสู้วิธีการใช้ไอเทมเป็นไอเทมรักษาในขณะที่ ThrowComponent บอกเครื่องมือต่อสู้ว่าจะรักษาไอเทมเป็นไอเทมที่สามารถโยนได้

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

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

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

คำตอบ:


8

ดูเหมือนขั้นตอนแรกที่สมเหตุสมผลมาก

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

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

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

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

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

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

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

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


1
+1 สำหรับการแนะนำการกำจัดวัตถุรายการ ในขณะที่มันจะทำงานได้ล่วงหน้ามากขึ้น แต่ก็จะสร้างระบบส่วนประกอบที่ดีขึ้น
James

ฉันมีคำถามอีกสองสามข้อไม่แน่ใจว่าฉันควรเริ่ม topiuc ใหม่หรือไม่ลองไปที่นี่ก่อน: สำหรับคลาสไอเท็มของฉันไม่มีวิธีใดที่ฉันจะเรียกเฟรม evert (หรือปิด) สำหรับระบบย่อยกราฟิกของฉันฉันจะใช้คำแนะนำของคุณและเก็บวัตถุทั้งหมดเพื่ออัปเดตภายใต้ระบบ คำถามอื่น ๆ ที่ฉันมีคือฉันจะจัดการกับการตรวจสอบส่วนประกอบได้อย่างไร เช่นฉันต้องการดูว่าฉันสามารถใช้ไอเท็มเป็น X ได้หรือไม่ดังนั้นโดยปกติฉันจะตรวจสอบว่าไอเท็มนั้นมีองค์ประกอบที่จำเป็นในการดำเนินการ X หรือไม่นี่เป็นวิธีที่ถูกต้องใช่ไหม ขอบคุณอีกครั้งสำหรับคำตอบ
user127817
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.