จะหลีกเลี่ยง“ Blob-Systems” ในระบบองค์ประกอบของเอนทิตี้ได้อย่างไร?


10

ขณะนี้ฉันกำลังประสบปัญหาต่อไปนี้:

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

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

แต่ปัญหาที่แท้จริงคือระบบการชนของฉัน ชั้นนี้เป็นเหมือนหยดตรรกะ ฉันมีคดีพิเศษมากมายในชั้นนี้

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

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

ฉันเห็นว่าระบบองค์ประกอบของเอนทิตีเป็นสิ่งที่ดีเพราะมีความยืดหยุ่นและคุณไม่มีปัญหาเกี่ยวกับการสืบทอด แต่ตอนนี้ฉันติดอยู่ทั้งหมด

ฉันคิดว่าซับซ้อนเกินไปหรือไม่ ฉันจะรับมือกับปัญหานี้ได้อย่างไร

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

แต่นี่ดูเหมือนจะไม่ใช่วิธีที่เหมาะสมสำหรับฉันเช่นกันเพราะตัวอย่างเช่น:

  1. ระบบหลังการชนกันของการเคลื่อนไหวของฉันต้องการหน่วยงานที่มีองค์ประกอบตำแหน่งส่วนประกอบการเคลื่อนไหวและส่วนประกอบการชนกัน จากนั้นมันจะตั้งค่าความเร็วของเอนทิตีเป็นศูนย์
  2. ระบบฟิสิกส์หลังการชนจะต้องการเอนทิตีที่มีองค์ประกอบตำแหน่ง, ส่วนประกอบการเคลื่อนไหว, ส่วนประกอบการชนและส่วนประกอบฟิสิกส์ จากนั้นมันก็จะสะท้อนเวกเตอร์ความเร็ว

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

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

คำตอบ:


11

ใช่คุณกำลังคิดซับซ้อนเกินไป

ดูเหมือนว่าปัญหาของคุณมากมายสามารถแก้ไขได้ด้วยระบบการส่งข้อความและคุณลักษณะเพิ่มเติมบางอย่างที่ช่วยให้คุณระบุตัวกรองบางตัวและในที่สุดก็ไม่ต้องกังวลกับความเข้มงวดของเอนทิตี / ส่วนประกอบ

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

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

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


ขอบคุณมาก. ฉันต้องการสร้างเกมโดยใช้ ECS เพียงเพื่อดูว่ามันขยายขนาดได้อย่างไรและถ้ามันใช้งานได้ดีจริงๆอย่างที่ฉันอ่านในบทความและแบบฝึกหัด ปัญหาของฉันคือฉันคิดว่า: "ตอนนี้ฉันมี ECS และทุกอย่างต้องได้รับการจัดการโดยสิ่งนี้" ดังนั้นฉันจึงวางแผนที่จะเขียนระบบอนุภาคที่เกี่ยวข้องกับ ECS นอกจากนี้ฉันอ่านในบางบทความว่าทุกองค์ประกอบควรมีข้อมูลพื้นฐานเท่านั้นและไม่มีอะไรเพิ่มเติม นั่นเป็นปัญหาของฉัน ... ฉันคิดว่าซับซ้อนเกินไป
M0rgenstern

ผมอยากจะสร้างเกมโดยใช้ ECS เพียงเพื่อดูวิธีการชั่งน้ำหนักและถ้ามันเป็นจริงที่ดีที่จะใช้เป็นผมอ่านในบทความและแบบฝึกหัด หากนั่นคือเป้าหมายของคุณฉันขอแนะนำให้คุณดูระบบ Component / Entity ที่มีอยู่แทนที่จะสร้างระบบของคุณเอง ดาวน์โหลด Unity3D ซึ่งอาจเป็น "องค์ประกอบที่บริสุทธิ์ที่สุดเท่าที่จะทำได้" และเล่นที่นั่น ข้อมูลเชิงลึกที่รวดเร็วยิ่งขึ้น IMHO
Imi

3
@lmi: Unity ไม่ใช่ Entity Component System แม้ว่าจะเป็นแบบ component ECS มีแนวทางที่ค่อนข้างเข้มงวด ( ไม่เคยคิดว่ารูปแบบเป็นกฎ) มากกว่าเพียงแค่มีและใช้ส่วนประกอบของเกม เนื่องจากบทความหลายบทความ ECS ได้รับความนิยมในกลุ่มนักพัฒนาเกมบางตอนดังนั้นจึงมีคำถามมากมายเกี่ยวกับ ECS โดยเฉพาะแทนที่จะออกแบบตามส่วนประกอบโดยทั่วไป
Sean Middleditch

12

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

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

ก่อนอื่นอย่าทำให้ส่วนประกอบของคุณเล็ก ไม่มีเหตุผลที่จะมีส่วนประกอบที่ละเอียดเหมือน 'การเคลื่อนไหว' ไม่มีการเคลื่อนไหวทั่วไปในเกมของคุณ คุณมีไม้พายที่มีการเคลื่อนไหวผูกติดกับอินพุตหรือ AI อย่างแน่นหนา (และไม่ใช้ความเร็วการเร่งความเร็วการชดใช้ความเสียหาย ฯลฯ ) และคุณมีลูกบอลซึ่งมีอัลกอริทึมการเคลื่อนไหวที่กำหนดชัดเจน เพียงแค่มีส่วนประกอบ PaddleController และส่วนประกอบ BouncingBall หรือบางอย่างตามสายเหล่านั้น หาก / เมื่อคุณได้รับเกมที่มีความซับซ้อนมากขึ้นคุณสามารถกังวลเกี่ยวกับองค์ประกอบ PhysicsBody ทั่วไป (ซึ่งในเอ็นจิน 'จริง' นั้นเป็นเพียงการเชื่อมโยงระหว่างวัตถุเกมและวัตถุ API ภายในใด ๆ ที่ใช้โดย Havok / PhysX / Bullet / Box2D / ฯลฯ ) ที่จัดการสถานการณ์ที่หลากหลาย

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

สำหรับเครื่องยนต์ฟิสิกส์ที่กำหนดเองโปรดจำไว้ว่าคุณได้รับอนุญาตให้มีข้อมูลเกี่ยวกับส่วนประกอบของคุณ บางทีส่วนประกอบฟิสิกส์พงษ์ทั่วไปมีข้อมูลที่ระบุว่าแกนใดที่มันสามารถเคลื่อนที่ได้ (พูดว่าvec2(0,1)เป็นตัวคูณสำหรับไม้พายซึ่งสามารถเคลื่อนที่บนแกน Y และvec2(1,1)สำหรับลูกบอลที่ระบุว่าสามารถเคลื่อนที่ได้) ธงหรือลอยแสดงถึงการเด้ง ( โดยทั่วไปแล้วลูกบอลจะอยู่ที่1.0และพายที่0.0) ลักษณะการเร่งความเร็วความเร็วและอื่น ๆ การพยายามแบ่งสิ่งนี้ออกเป็นองค์ประกอบไมโครที่แตกต่างกันหลายพันล้านชิ้นสำหรับข้อมูลที่เกี่ยวข้องสูงแต่ละชิ้นนั้นตรงกันข้ามกับสิ่งที่ ECS เดิมตั้งใจจะทำ เก็บสิ่งต่าง ๆ ที่ใช้ร่วมกันในองค์ประกอบเดียวกันเท่าที่จะทำได้และแยกออกเมื่อมีความแตกต่างอย่างมากในวิธีที่แต่ละเกมของวัตถุใช้ข้อมูลนั้น มีการโต้เถียงกันว่าสำหรับพงษ์ฟิสิกส์ระหว่างลูกบอลและไม้พายแตกต่างกันพอที่จะแยกส่วนประกอบ แต่สำหรับเกมที่มีขนาดใหญ่ขึ้นมีเหตุผลเล็กน้อยที่จะลองทำ 20 องค์ประกอบเพื่อทำงานได้ดีใน 1-3

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


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

1
อะไรก็ตามที่ใช้งานได้ มุ่งเน้นการสร้างเกม แท้จริงฉันจะมีองค์ประกอบที่เรียกว่าBallที่ประกอบด้วยตรรกะทั้งหมดสำหรับลูกบอลเช่นการเคลื่อนไหวกระดอน ฯลฯ และPaddleส่วนประกอบที่รับอินพุต แต่นั่นคือฉัน อะไรก็ตามที่เหมาะสมกับคุณมากที่สุดและออกไปให้พ้นและช่วยให้คุณทำให้เกมเป็น "วิธีที่ถูกต้อง" ในการทำสิ่งต่าง ๆ
Sean Middleditch

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

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

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

-2

ในความเห็นของฉัน *) ปัญหาที่ใหญ่ที่สุดของคุณเกี่ยวกับส่วนประกอบคือ: ส่วนประกอบไม่ได้อยู่ที่นี่เพื่อบอกให้คนอื่นทำอะไร ส่วนประกอบอยู่ที่นี่เพื่อทำสิ่งต่างๆ คุณไม่ได้มีส่วนประกอบเพียงเพื่อเก็บความทรงจำของบางสิ่งและจากนั้นให้ส่วนประกอบอื่นทำงานกับสิ่งนี้ คุณต้องการส่วนประกอบที่ทำสิ่งต่าง ๆ กับข้อมูลที่ได้รับ

หากคุณเห็นว่าคุณกำลังทดสอบส่วนประกอบอื่น ๆ (และเรียกใช้ฟังก์ชันที่นั่น) นี่เป็นสัญญาณที่ชัดเจนว่าหนึ่งในสองสิ่งนี้เป็นจริง:

  • คุณต้องการคว่ำการพึ่งพา: องค์ประกอบอื่น ๆ ควรฟังเหตุการณ์ / ข้อความ / Broadcasts / hooks / howeveryounamethem เพื่อรันตรรกะของพวกเขาในการตอบสนองขององค์ประกอบปัจจุบันของคุณ องค์ประกอบปัจจุบันไม่จำเป็นต้องรู้ด้วยซ้ำว่ามีองค์ประกอบ "อื่น ๆ " นี่คือกรณีส่วนใหญ่หากคุณพบว่าตัวเองโทรหาส่วนประกอบที่แตกต่างกัน (แม้จะอยู่ในบล็อกอื่น / บล็อกอื่น) ด้วยฟังก์ชันการทำงานที่ไม่ได้เชื่อมต่อกับวิธีการปัจจุบันของคุณ ลองนึกถึงสิ่งเหล่านี้Invalidate()หรือSetDirty()เรียกไปยังส่วนประกอบอื่น ๆ
  • คุณอาจมีองค์ประกอบมากเกินไป หากสององค์ประกอบไม่สามารถอยู่ได้โดยปราศจากซึ่งกันและกันและจำเป็นต้องดึงข้อมูลและวิธีการโทรหากันอย่างต่อเนื่องจากนั้นก็รวมมันเข้าด้วยกัน เห็นได้ชัดว่าฟังก์ชั่นที่พวกเขาให้นั้นพัวพันกันจริงๆ

โดยวิธีการเหล่านี้นำไปใช้กับระบบทุกประเภทไม่เพียง แต่ระบบ Entity / Component แต่ยังรวมถึงการสืบทอดแบบคลาสสิกด้วยฟังก์ชั่น "GameObject" หรือแม้แต่ห้องสมุดที่เรียบง่าย

*) จริงๆเพียงเหมือง ความคิดเห็นแตกต่างกันอย่างมากเกี่ยวกับWhats Da Real Component Systemz (TM)

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