เราเริ่มต้นจากขั้นพื้นฐานวิธีการระบบส่วนประกอบที่มีหน่วยงาน
ขอสร้างassemblages (ระยะที่ได้มาจากนี้บทความ) เพียงออกของข้อมูลเกี่ยวกับชนิดของชิ้นส่วน มันจะทำแบบไดนามิกที่รันไทม์เช่นเดียวกับที่เราจะเพิ่ม / ลบส่วนประกอบไปยังเอนทิตีทีละคน แต่ขอเพียงแค่ตั้งชื่อได้อย่างแม่นยำมากขึ้นเพราะมันเป็นเพียงเกี่ยวกับข้อมูลประเภท
แล้วเราจะสร้างหน่วยงานที่ระบุการชุมนุมทุกครั้งของพวกเขา เมื่อเราสร้างเอนทิตีแล้วชุดประกอบของมันจะไม่เปลี่ยนรูปซึ่งหมายความว่าเราไม่สามารถแก้ไขได้โดยตรง แต่ก็ยังสามารถรับลายเซ็นของเอนทิตีที่มีอยู่ไปยังสำเนาภายในเครื่อง (พร้อมกับเนื้อหา) ทำการเปลี่ยนแปลงที่เหมาะสมและสร้างเอนทิตีใหม่ ของมัน
ตอนนี้สำหรับแนวคิดหลัก: เมื่อใดก็ตามที่มีการสร้างเอนทิตีมันจะถูกกำหนดให้กับวัตถุที่เรียกว่าbucket bucketlageซึ่งหมายความว่าเอนทิตีทั้งหมดของลายเซ็นเดียวกันจะอยู่ในคอนเทนเนอร์เดียวกัน (เช่นใน std :: vector)
ตอนนี้ระบบเพียงทำซ้ำผ่านทุกกลุ่มที่สนใจและทำงานของพวกเขา
วิธีนี้มีข้อดีดังนี้
- ส่วนประกอบถูกเก็บไว้ในหน่วยความจำที่ต่อเนื่องกันสองสามชิ้น (แม่นยำ: จำนวนถัง) - ช่วยเพิ่มความเป็นมิตรกับหน่วยความจำและง่ายต่อการทิ้งสถานะเกมทั้งหมด
- ระบบประมวลผลองค์ประกอบในลักษณะเชิงเส้นซึ่งหมายถึงการปรับปรุงการเชื่อมโยงกันแคช - ลาก่อนพจนานุกรมและหน่วยความจำแบบสุ่มกระโดด
- การสร้างเอนทิตีใหม่นั้นง่ายเหมือนการทำแผนที่ชุดประกอบเพื่อฝากข้อมูลและผลักดันส่วนประกอบที่ต้องการกลับไปยังเวกเตอร์
- การลบเอนทิตีเป็นเรื่องง่ายเหมือนกับการเรียก std :: move เพื่อสลับองค์ประกอบสุดท้ายกับอันที่ถูกลบเพราะลำดับไม่สำคัญในตอนนี้
หากเรามีเอนทิตีจำนวนมากที่มีลายเซ็นที่แตกต่างกันโดยสิ้นเชิงประโยชน์ของการเชื่อมโยงกันของแคชลดน้อยลง แต่ฉันไม่คิดว่ามันจะเกิดขึ้นในแอปพลิเคชันส่วนใหญ่
นอกจากนี้ยังมีปัญหาเกี่ยวกับการทำให้ตัวชี้ใช้ไม่ได้เมื่อมีการจัดสรรเวกเตอร์ใหม่ซึ่งสามารถแก้ไขได้โดยการแนะนำโครงสร้างเช่น:
struct assemblage_bucket {
struct entity_watcher {
assemblage_bucket* owner;
entity_id real_index_in_vector;
};
std::unordered_map<entity_id, std::vector<entity_watcher*>> subscribers;
//...
};
ดังนั้นเมื่อมีเหตุผลบางอย่างในตรรกะเกมของเราเราต้องการติดตามเอนทิตีที่สร้างขึ้นใหม่ภายในที่เก็บข้อมูลเราลงทะเบียนเอนทิตีวอลเนอร์และเมื่อเอนทิตีจะต้องเป็นมาตรฐาน :: move'd ระหว่างการลบ ของพวกเขาreal_index_in_vector
ให้เป็นค่าใหม่ ส่วนใหญ่เวลานี้กำหนดให้มีการค้นหาพจนานุกรมเพียงครั้งเดียวสำหรับการลบเอนทิตีทุกอัน
มีข้อเสียเพิ่มเติมสำหรับแนวทางนี้หรือไม่?
ทำไมถึงไม่มีวิธีการแก้ปัญหาที่กล่าวถึงแม้จะค่อนข้างชัดเจน?
แก้ไข : ฉันแก้ไขคำถามเพื่อ "ตอบคำตอบ" เนื่องจากความคิดเห็นไม่เพียงพอ
คุณสูญเสียลักษณะไดนามิกของส่วนประกอบที่เสียบได้ซึ่งสร้างขึ้นโดยเฉพาะเพื่อหลีกเลี่ยงการสร้างคลาสแบบสแตติก
ฉันไม่. บางทีฉันไม่ได้อธิบายอย่างชัดเจนพอ:
auto signature = world.get_signature(entity_id); // this would just return entity_id.bucket_owner->bucket_signature or so
signature.add(foo_component);
signature.remove(bar_component);
world.delete_entity(entity_id); // entity_id would hold information about its bucket owner
world.create_entity(signature); // automatically assigns new entity to an existing or a new bucket
มันง่ายเหมือนการรับลายเซ็นของเอนทิตีที่มีอยู่ดัดแปลงและอัปโหลดอีกครั้งเป็นเอนทิตีใหม่ เป็นธรรมชาติแบบไดนามิกได้หรือไม่ แน่นอน. ที่นี่ฉันต้องการเน้นว่ามีเพียง "การชุมนุม" และ "ถัง" หนึ่งชั้น ที่เก็บข้อมูลขับเคลื่อนด้วยข้อมูลและสร้างเมื่อใช้งานจริงในปริมาณที่เหมาะสม
คุณจะต้องผ่านถังทั้งหมดที่อาจมีเป้าหมายที่ถูกต้อง หากไม่มีโครงสร้างข้อมูลภายนอกการตรวจจับการชนอาจทำได้ยากพอ ๆ กัน
ดีนี้เป็นเหตุผลที่เรามีดังกล่าวโครงสร้างข้อมูลภายนอก วิธีแก้ปัญหานั้นง่ายพอ ๆ กับการแนะนำตัววนซ้ำในคลาสระบบที่ตรวจพบว่าเมื่อใดจะข้ามไปที่ฝากข้อมูลถัดไป การกระโดดจะต้องโปร่งใสอย่างมีเหตุผล