เมื่อไหร่ / ที่ไหนที่จะอัพเดทส่วนประกอบ


10

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

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

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

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

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


1
คุณกำลังใช้ระบบอย่างใด?
Asakeron

ระบบส่วนประกอบเป็นวิธีปกติในการทำเช่นนี้ ฉันเป็นการส่วนตัวเพียงแค่เรียกการอัปเดตเกี่ยวกับเอนทิตีทั้งหมดซึ่งเรียกการอัปเดตในส่วนประกอบทั้งหมดและมีบางกรณี "พิเศษ" (เช่นตัวจัดการเชิงพื้นที่สำหรับการตรวจจับการชนกันของข้อมูลซึ่งเป็นแบบคงที่)
ashes999

ระบบส่วนประกอบ ฉันไม่เคยได้ยินชื่อพวกนี้มาก่อน ฉันจะเริ่ม Googling แต่ฉันยินดีต้อนรับลิงก์ที่แนะนำ
รอยต.

1
ระบบ Entity เป็นอนาคตของการพัฒนา MMOGเป็นทรัพยากรที่ยอดเยี่ยม และตามจริงฉันมักจะสับสนกับชื่อสถาปัตยกรรมเหล่านี้ ความแตกต่างกับวิธีการที่แนะนำคือส่วนประกอบจะเก็บข้อมูลและระบบได้เท่านั้น คำตอบนี้มีความเกี่ยวข้องเช่นกัน
Asakeron

1
ฉันเขียนโพสต์บล็อกแบบคดเคี้ยวในหัวข้อนี้ที่นี่: gamedevrubberduck.wordpress.com/2012/12/26/ …
AlexFoxGill

คำตอบ:


15

ฉันขอแนะนำให้เริ่มต้นด้วยการอ่านคำโกหกที่ยิ่งใหญ่ของ Mike Acton เพราะคุณละเมิดทั้งสอง ฉันจริงจังนี่จะเปลี่ยนวิธีที่คุณออกแบบรหัสของคุณ: http://cellperformance.beyond3d.com/articles/2008/03/three-big-lies.html

แล้วคุณทำอะไรละเมิด?

โกหก # 3 - รหัสสำคัญกว่าข้อมูล

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

private CollissionManager _collissionManager;
private BulletManager _bulletManager;

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

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

Lie # 2 - รหัสควรได้รับการออกแบบรอบ ๆ แบบจำลองของโลก

ดังนั้นคุณมีเอนทิตีในโลกของเกม เอนทิตีมีจำนวนขององค์ประกอบที่กำหนดพฤติกรรมของมัน ดังนั้นคุณต้องสร้างคลาส Entity ด้วยรายการของออบเจกต์ Component และฟังก์ชัน Update () ซึ่งเรียกใช้ฟังก์ชัน Update () ของแต่ละ Component ขวา?

Nope :) นั่นคือการออกแบบรอบ ๆ แบบจำลองของโลก: คุณมีสัญลักษณ์แสดงหัวข้อย่อยในเกมของคุณดังนั้นคุณจึงเพิ่มคลาสกระสุน จากนั้นคุณอัปเดตกระสุนแต่ละอันและไปยังกระสุนถัดไป สิ่งนี้จะทำให้ประสิทธิภาพการทำงานของคุณแย่ลงและมันจะช่วยให้คุณมี codebase ที่ซับซ้อนที่น่ากลัวด้วยรหัสที่ซ้ำกันได้ทุกที่ (ตรวจสอบคำตอบของฉันที่นี่สำหรับคำอธิบายโดยละเอียดเพิ่มเติมเกี่ยวกับสาเหตุที่การออกแบบ OO แบบดั้งเดิมแย่ลงหรือค้นหา Data Oriented Design)

ลองดูสถานการณ์โดยไม่มีอคติ OO ของเรา เราต้องการสิ่งต่อไปนี้ไม่มากไม่น้อย (โปรดทราบว่าไม่มีข้อกำหนดในการสร้างคลาสสำหรับเอนทิตีหรือวัตถุ):

  • คุณมีเอนทิตี้มากมาย
  • เอนทิตีประกอบด้วยจำนวนขององค์ประกอบที่กำหนดพฤติกรรมของกิจการ
  • คุณต้องการอัปเดตแต่ละองค์ประกอบในเกมแต่ละเฟรมโดยเฉพาะอย่างยิ่งในวิธีการควบคุม
  • นอกเหนือจากการระบุส่วนประกอบที่เป็นของร่วมกันไม่มีสิ่งใดที่เอนทิตีเองต้องทำ มันเป็นลิงค์ / ID สำหรับส่วนประกอบสองสามอย่าง

ลองดูที่สถานการณ์ ระบบส่วนประกอบของคุณจะอัพเดตพฤติกรรมของทุกวัตถุในเกมทุกเฟรม นี่เป็นระบบที่สำคัญอย่างยิ่งสำหรับเครื่องยนต์ของคุณ ประสิทธิภาพเป็นสิ่งสำคัญที่นี่!

หากคุณคุ้นเคยกับสถาปัตยกรรมคอมพิวเตอร์หรือ Data Oriented Design คุณจะรู้ว่าประสิทธิภาพการทำงานที่ดีที่สุดนั้นเป็นอย่างไร: หน่วยความจำที่บรรจุแน่นและการประมวลผลรหัสกลุ่ม หากคุณเรียกใช้ตัวอย่างโค้ด A, B และ C ดังนี้: ABCABCABC คุณจะไม่ได้รับประสิทธิภาพเช่นเดียวกับเมื่อคุณเรียกใช้งานเช่นนี้: AAABBBCCC นี่ไม่ใช่เพียงเพราะการเรียนการสอนและแคชข้อมูลจะถูกใช้อย่างมีประสิทธิภาพมากขึ้น แต่ยังเพราะถ้าคุณดำเนินการ "A" ทั้งหมดหลังจากนั้นอีกครั้งมีพื้นที่มากมายสำหรับการปรับให้เหมาะสม: การลบรหัสที่ซ้ำกัน ทั้งหมด "A" s เป็นต้น

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

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

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

สิ่งที่เราจำเป็นต้องมีก็คือ Entity Manager คลาสนี้จะสร้าง ID ที่ไม่ซ้ำกันถ้าคุณใช้วิธีแก้ปัญหา ID เท่านั้นหรือสามารถใช้เพื่อสร้าง / จัดการวัตถุ Entity นอกจากนี้ยังสามารถเก็บรายการของเอนทิตีทั้งหมดในเกมหากคุณต้องการ Entity Manager อาจเป็นคลาสกลางของระบบส่วนประกอบของคุณจัดเก็บข้อมูลอ้างอิงไปยัง ComponentManagers ทั้งหมดในเกมของคุณและเรียกใช้ฟังก์ชั่นการอัพเดทตามลำดับที่ถูกต้อง วิธีนี้ทำให้วนรอบเกมต้องทำคือเรียก EntityManager.update () และระบบทั้งหมดจะถูกแยกออกจากส่วนที่เหลือของเครื่องยนต์ของคุณ

นั่นคือมุมมองแบบเบิร์ดลองมาดูกันว่าผู้จัดการองค์ประกอบทำงานอย่างไร นี่คือสิ่งที่คุณต้องการ:

  • สร้างข้อมูลองค์ประกอบเมื่อสร้าง (entityID) ถูกเรียก
  • ลบข้อมูลส่วนประกอบเมื่อมีการลบ (entityID) เรียก
  • อัปเดตข้อมูลส่วนประกอบทั้งหมด (ใช้งานได้) เมื่อเรียกใช้อัปเดต () (เช่นไม่ใช่ส่วนประกอบทั้งหมดที่จำเป็นต้องอัปเดตแต่ละเฟรม)

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

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

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

จากนั้นมีสิ่งหนึ่งที่สุดท้ายคือการสื่อสารและการแบ่งปันข้อมูลระหว่างส่วนประกอบ ตอนนี้มันยุ่งยากและไม่มีวิธีแก้ปัญหาที่เหมาะกับทุกขนาด คุณสามารถสร้างฟังก์ชั่น get / set ในตัวจัดการเพื่ออนุญาตให้อินสแตนซ์ส่วนประกอบการชนกันเพื่อรับตำแหน่งจากองค์ประกอบตำแหน่ง (เช่น PositionManager.getPosition (เอนทิตี)) คุณสามารถใช้ระบบเหตุการณ์ คุณสามารถจัดเก็บข้อมูลที่ใช้ร่วมกันบางอย่างในเอนทิตี (ทางออกที่น่าเกลียดที่สุดในความคิดของฉัน) คุณสามารถใช้ (มักใช้) ระบบการส่งข้อความ หรือใช้การรวมกันของหลาย ๆ ระบบ! ฉันไม่มีเวลาหรือประสบการณ์ในการเข้าสู่แต่ละระบบเหล่านี้ แต่การค้นหา google และ stackoverflow เป็นเพื่อนของคุณ


ฉันพบว่าคำตอบนี้น่าสนใจมาก เพียงหนึ่งคำถาม (หวังว่าคุณหรือใครบางคนสามารถตอบฉันได้) คุณจะจัดการกำจัดเอนทิตีบนระบบที่อิงองค์ประกอบ DOD ได้อย่างไร แม้แต่อาร์ทิมิสก็ใช้ Entity เป็นคลาสฉันก็ไม่แน่ใจ
Wolfrevo Kcats

1
คุณหมายถึงอะไรโดยกำจัดมัน คุณหมายถึงระบบเอนทิตีที่ไม่มีคลาสเอนทิตีหรือไม่? เหตุผลที่อาร์ทิมิสมีเอนทิตีเพราะในอาร์ทิมิสคลาสเอนทิตีจัดการองค์ประกอบของตนเอง ในระบบที่ฉันเสนอคลาส ComponentManager จะจัดการส่วนประกอบต่างๆ ดังนั้นแทนที่จะต้องการคลาส Entity คุณสามารถมี ID จำนวนเต็มเฉพาะได้ สมมุติว่าคุณมีเอนทิตี 254 ซึ่งมีองค์ประกอบตำแหน่ง เมื่อคุณต้องการเปลี่ยนตำแหน่งคุณสามารถเรียก PositionCompMgr.setPosition (int id, Vector3 newPos) โดยมี 254 เป็นพารามิเตอร์ id
Mart

แต่คุณจะจัดการ ID ได้อย่างไร จะทำอย่างไรถ้าคุณต้องการลบส่วนประกอบจากเอนทิตีเพื่อกำหนดให้กับคอมโพเนนต์อื่นในภายหลัง ถ้าคุณต้องการลบเอนทิตีและเพิ่มอันใหม่? จะทำอย่างไรถ้าคุณต้องการแบ่งปันองค์ประกอบหนึ่งระหว่างเอนทิตี้สองแห่งหรือมากกว่า ฉันสนใจสิ่งนี้จริงๆ
Wolfrevo Kcats

1
EntityManager สามารถใช้เพื่อแจก ID ใหม่ นอกจากนี้ยังสามารถใช้เพื่อสร้างเอนทิตีที่สมบูรณ์ตามแม่แบบที่กำหนดไว้ล่วงหน้า (เช่นสร้าง "EnemyNinja" ซึ่งสร้าง ID ใหม่และสร้างส่วนประกอบทั้งหมดที่ประกอบเป็นนินจาศัตรูเช่นที่สามารถแสดงได้การชนกัน AI อาจเป็นส่วนประกอบสำหรับการต่อสู้ประชิด ฯลฯ ) นอกจากนี้ยังสามารถมีฟังก์ชั่น removeEntity ซึ่งจะเรียกฟังก์ชั่นลบ ComponentManager ทั้งหมดโดยอัตโนมัติ ComponentManager สามารถตรวจสอบว่ามีข้อมูลส่วนประกอบสำหรับ Entity ที่กำหนดหรือไม่และให้ลบข้อมูลนั้นหรือไม่
Mart

1
ย้ายส่วนประกอบจากเอนทิตีหนึ่งไปอีกอันหนึ่งหรือไม่? เพียงเพิ่มฟังก์ชั่น swapComponentOwner (int oldEntity, newEntity int) ให้กับแต่ละ ComponentManager ข้อมูลมีอยู่ใน ComponentManager สิ่งที่คุณต้องมีคือฟังก์ชั่นเพื่อเปลี่ยนเจ้าของที่เป็นเจ้าของ ComponentManager แต่ละอันจะมีดัชนีหรือแผนที่เพื่อเก็บข้อมูลที่เป็นของเอนทิตี้ของ ID เพียงแค่เปลี่ยนรหัสเอนทิตีจากเก่าเป็น ID ใหม่ ฉันไม่แน่ใจว่าการแบ่งปันองค์ประกอบเป็นเรื่องง่ายในระบบที่ฉันคิดขึ้นมา แต่มันยากแค่ไหน? แทนที่จะเป็นลิงค์เอนทิตี ID เดียว <-> ข้อมูลคอมโพเนนต์ในตารางดัชนีมีหลายรายการ
Mart

3

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

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

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

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

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

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

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

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

วิธีการนี้บางครั้งเรียกว่าวิธีการส่วนประกอบนอกเรือหากคุณกำลังมองหารายละเอียดเพิ่มเติม

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