จะจัดการกับการชนในเกมที่มีส่วนประกอบได้อย่างไร


11

พยายามพาดหัวของฉันในการจัดการกับการชนในเกมที่ออกแบบมาสำหรับส่วนประกอบต่างๆ

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

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

สำหรับฉันแล้วมันดูเหมือนว่าระดับหรือฉากควรรักษารายการของเอนทิตีเหล่านี้และการอัปเดตเกมทุกครั้ง

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

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

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

สมมติว่าทั้งสองเอนทิตีมี HealthComponent และเมื่อพวกเขาชนทั้งสุขภาพของพวกเขาจะลดลงตามมูลค่าโดยพลการ 5. ฉันคิดว่ามันเป็นความรับผิดชอบของฉากที่จะจัดการเรื่องนี้เมื่อตรวจพบการชนกันระหว่างสองเอนทิตี้?

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

แก้ไข:คำถามได้รับการอัปเดตพร้อมรายละเอียดเพิ่มเติม


4
คำตอบนี้ดูเหมือนว่าเหมาะสมที่จะเชื่อมโยงไปยัง: gamedev.stackexchange.com/questions/13797/ …
Andrew Russell

คำตอบที่เชื่อมโยงของ Andrew คำตอบของ James และคำตอบของ Nick Wiggill สมควรได้รับ +1 ทั้งหมด คิดว่าส่วนประกอบเป็นข้อมูลมากกว่าชั้นเรียนทั่วไปที่มีทั้งข้อมูลและวิธีการ (ไม่ใช่ว่าพวกเขาจะไม่มีวิธีการ แต่พวกเขาไม่ควรรับผิดชอบมาก) ดูที่ระบบคอมโพเนนต์ของ Artemis ( piemaster.net/2011/07/entity-component-artemis ) สำหรับตัวอย่างของกรอบองค์ประกอบที่ดี
michael.bartnett

คำตอบ:


5

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

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

ฉันคิดว่าคุณอยู่ในเส้นทางที่ถูกต้องและต้องการ 'ใช่ฟังดูดี' ดังนั้น .. ใช่ฟังดูดี

หวังว่านี่จะช่วยได้!


3

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

สำหรับ 2D ห้องสมุดฟิสิกส์ฟรีที่รู้จักกันดีคือ Box2D นอกจากนี้ยังคุ้มค่าที่จะดู Chipmunk สำหรับ 3D กระสุนฟรี (อาจเป็นเกมที่ดีที่สุดที่คุณหาได้) Havok และ PhysX มีชื่อเสียงในการใช้ในเกมสามเกมจำนวนมาก


2

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

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


2

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

ฉันใช้ Box2D ที่คุณสามารถแนบ "ผู้ฟังแบบชนกัน" ซึ่งจะได้รับแจ้งจากการชน เนื่องจากฉันเพิ่มตัวชี้ไปที่ "ColliderComponent" ของฉันกับข้อมูลผู้ใช้ bodys ฉันจึงสามารถรับ ColliderComponents สองรายการของฉันซึ่งเป็นส่วนหนึ่งของการชนกัน

ดังนั้นสิ่งที่เกิดขึ้นเมื่อมีการชนกันคือ: ColliderComponents ซึ่งเป็นส่วนหนึ่งของการชนจะส่งข้อความไปยังเจ้าของวัตถุ (เกม - เอนทิตี) ซึ่งจะส่งข้อความนั้นไปยังส่วนประกอบทั้งหมด

ทุกองค์ประกอบสามารถตอบสนองต่อข้อความนั้นดังนั้น "สุขภาพ - องค์ประกอบ" ของคุณสามารถลบ 5 คะแนนจากสุขภาพ ฯลฯ


+1: ฉันใช้วิธีการที่คล้ายกันมาก คุณจะกำหนดจำนวนความเสียหายที่จะเกิดขึ้นได้อย่างไรขึ้นอยู่กับประเภทของเอนทิตีที่ชนกัน
ชัด

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

0

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

โชคดี. ฉันพบว่าระบบการชนเป็นส่วนที่น่าเบื่อของเอ็นจิ้นเกม

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