ในเอ็นจินเอ็นติตี้ - คอมโพเนนต์ - ระบบฉันจะจัดการกับกลุ่มของเอนทิตีที่พึ่งพาได้อย่างไร


47

หลังจากผ่านรูปแบบการออกแบบเกมมาสองสามครั้งฉันได้ตกลงกับ Entity-Component-System (ระบบ ES) สำหรับเอ็นจิ้นเกมของฉัน ฉันอ่านบทความ (ส่วนใหญ่เป็นT = Machine ) และตรวจสอบซอร์สโค้ดและฉันคิดว่าฉันเริ่มต้นได้เพียงพอแล้ว

มีเพียงแนวคิดพื้นฐานเดียวที่ฉันกำลังดิ้นรนอยู่ ฉันจะจัดการกับกลุ่มของเอนทิตีที่ต้องพึ่งพาซึ่งกันและกันได้อย่างไร

ให้ฉันใช้ตัวอย่าง:

สมมติว่าฉันสร้างปืนเหนือศีรษะแบบมาตรฐาน (คิดว่าเจมส์ทาวน์ ) และฉันต้องการสร้าง "หัวหน้าเอนทิตี" ที่มีหลายส่วนที่แตกต่างกัน แต่เชื่อมต่อกัน การพังทลายอาจมีลักษณะเช่นนี้:

  • ตัวเรือ: การเคลื่อนไหว, การแสดงผล
  • ปืนใหญ่: ตำแหน่ง (ล็อคโดยสัมพันธ์กับตัวเรือ), ติดตาม \ Fire ที่ฮีโร่, สร้างความเสียหายจนกว่าจะปิดการใช้งาน
  • แกนหลัก: ตำแหน่ง (ล็อคโดยสัมพันธ์กับตัวเรือ), การติดตาม \ Fire ที่ฮีโร่, ทำความเสียหายจนกว่าจะปิดการใช้งาน, ปิดใช้งาน (เอ่อ ... ทำลาย) เอนทิตีอื่น ๆ ทั้งหมดในกลุ่มเรือ

เป้าหมายของฉันจะเป็นสิ่งที่จะระบุ (และจัดการ) เป็นองค์ประกอบเกมที่แตกต่างโดยไม่ต้องเขียนระบบย่อยใหม่ทุกครั้งที่ฉันต้องการสร้างองค์ประกอบรวมใหม่

ฉันจะใช้การออกแบบประเภทนี้ในระบบ ES ได้อย่างไร

  1. ฉันจะใช้ความสัมพันธ์เอนทิตีระหว่างพ่อแม่และลูกหรือไม่ (เอนทิตีสามารถมีลูกได้)? สิ่งนี้ดูเหมือนจะขัดแย้งกับวิธีการที่เอนทิตีเป็นเพียงภาชนะที่ว่างเปล่าและทำให้มันรู้สึกว่า OOP มากขึ้น
  2. ฉันจะใช้มันเป็นเอนทิตี้ที่แยกต่างหากด้วยการเชื่อมต่อ Component (BossComponent) และระบบที่เกี่ยวข้อง (BossSubSystem) หรือไม่? ฉันอดไม่ได้ที่จะคิดว่าสิ่งนี้จะเป็นเรื่องยากที่จะนำมาใช้เนื่องจากการสื่อสารของส่วนประกอบดูเหมือนจะเป็นกับดักหมีตัวใหญ่
  3. ฉันจะใช้มันเป็น Entity เดียวด้วยชุดของส่วนประกอบ (ShipComponent, CannonComponents, CoreComponent) หรือไม่ อันนี้ดูเหมือนจะเปลี่ยนทิศทางของความตั้งใจของระบบ ES (ส่วนประกอบที่นี่ดูเหมือนมากเกินไปเอนทิตีที่มีน้ำหนักมาก) แต่ฉันรู้เรื่องนี้ดังนั้นฉันจึงคิดว่าฉันจะเอามันออกไป
  4. ฉันจะใช้มันเป็นอย่างอื่นที่ฉันได้กล่าวถึงหรือไม่

ฉันรู้ว่าสิ่งนี้สามารถนำไปใช้งานได้อย่างง่ายดายใน OOP แต่การเลือก ES มากกว่า OOP เป็นสิ่งที่ฉันจะทำ ถ้าฉันต้องการทำลายด้วยทฤษฎี ES ที่บริสุทธิ์เพื่อใช้การออกแบบนี้ฉันจะ (ไม่เหมือนที่ฉันไม่เคยมีการออกแบบที่บริสุทธิ์มาก่อน) แต่ฉันต้องการทำเช่นนั้นเพื่อเหตุผลด้านประสิทธิภาพแทนที่จะเริ่มต้นด้วยการออกแบบที่ไม่ดี

สำหรับเครดิตพิเศษลองนึกถึงการออกแบบที่เหมือนกัน แต่ "เอนทิตีของเจ้านาย" แต่ละอันนั้นเชื่อมโยงกับ "บิ๊กเอนทิตี BigBoss" ที่ทำจากตัวหลัก, แกนหลักและ 3 "เอนทิตีบอส" นี่จะให้ฉันดูวิธีแก้ปัญหาอย่างน้อย 3 มิติ (ปู่ย่าตายาย - ลูก - ลูก) ... ซึ่งน่าจะเพียงพอสำหรับฉัน


2
มันเป็นเพียงส่วนประกอบของเมชที่แตกต่างกันที่แนบมากับเอนทิตีเรือและปืนใหญ่ตาข่ายที่ติดอยู่กับเอนทิตีเจ้านาย Btw ระบบส่วนประกอบของเอนทิตี is OOP!
Maik Semder

2
ใช่ - สิ่งที่แย่กว่านั้นในบทความของ T-Machine คือความคิดที่ผิด ๆ ว่านี่ไม่เชิงวัตถุ ระบบส่วนประกอบส่วนใหญ่สำหรับเอนทิตีเป็นแบบเชิงวัตถุทั้งหมดไม่ใช่อิงตามการสืบทอด
Kylotan

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

@MaikSemder ฉันทำความสะอาดความคิดเห็นของฉันและย้ายพวกเขาไปแชท
MichaelHouse

1
เพียงแค่ฉันเข้าใจ @MaikSemder ในระบบ ES ของคุณการอ้างอิงเอนทิตีสามารถมีองค์ประกอบหลายประเภทเดียวกันและระบบย่อยที่รับผิดชอบส่วนประกอบเหล่านั้นจะต้องจัดการกับความจริงนั้นหรือไม่ ดังนั้นเอนทิตีสามารถมีส่วนประกอบ Render หลายตัวและข้อมูลและระบบย่อยของส่วนประกอบเหล่านั้นจะกำหนดวิธีการแสดงผลแต่ละองค์ประกอบอย่างถูกต้องหรือไม่ สิ่งนั้นจะนำไปสู่เอนทิตีที่น้อยลงส่วนประกอบที่อาจเกิดขึ้นน้อยลง แต่ตรรกะของระบบย่อยที่ลึกกว่านั้นถูกต้องไหม
John Daniels

คำตอบ:


41

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

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

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

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


ข้อมูลที่ดีมากมายที่นี่ คุณอธิบายวิธีแก้ปัญหาได้ดีลองดูตัวอย่างและอาจตอบคำถามอีก 1 หรือ 2 ข้อที่ฉันจะต้องกลับมาในภายหลัง การสนทนาที่เชื่อมโยงนั้นดูเหมือนว่าน่าสนใจโดยเฉพาะเมื่อฉันเริ่มที่จะนำไปใช้งานให้หนักขึ้น ขอบคุณ @ Byte56!
John Daniels

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

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

7

โดยไม่ทราบรายละเอียดมากเกินไปเกี่ยวกับระบบที่มีอยู่ของคุณวิธีที่ฉันจะสร้างแบบจำลองนี้ (และต้องมีขอบเขตในระบบเอนทิตีของตัวเอง) คือการมีส่วนประกอบเช่น AttachedTo (parentEntity) เด็ก ๆ สามารถได้รับองค์ประกอบ AttachedTo (boss)

ระบบการเรนเดอร์ (หรืออะไรก็ตาม) จะดึงเอนทิตีที่มีส่วนประกอบ: ตำแหน่ง, AttachedTo ฯลฯ และสร้างลำดับชั้นที่เหมาะสม


นี่น่าจะเป็นคำตอบที่สอดคล้องกัน ครั้งต่อไปฉันจะให้รายละเอียดเพิ่มเติมเกี่ยวกับการนำไปใช้เพื่อให้ผู้คนเคี้ยว ขอบคุณ @PSpeed!
John Daniels

4

ถ้าคุณต้องการที่จะมีนิติบุคคลที่เป็นตัวแทนเพียง ID จากนั้นการบรรจุของเอนทิตีสามารถทำได้ผ่านองค์ประกอบพิเศษ คุณสามารถเรียกมันว่า CompositeComponent และสิ่งนี้มีรายการรหัสเอนทิตีลูกและอินเทอร์เฟซเพื่อเพิ่ม / ลบชายด์ออกจากรายการนั้น

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

โดยวิธีการที่ไม่มี "ทฤษฎี ES บริสุทธิ์" - การสร้างเอนทิตีจากองค์ประกอบเป็นวิธีการที่นิยม แต่วิธีการที่แม่นยำยังไม่ได้มาตรฐาน


ใช่ฉันควรเรียนรู้ที่จะไม่ใช้คำว่า "บริสุทธิ์" ในการอภิปรายการออกแบบใด ๆ ... ไม่มีสิ่งนั้น เส้นทาง ConpositeComponent ดูเหมือนว่าฉันทามติที่นี่ ขอบคุณ @Kylotan!
John Daniels
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.