วิธีที่เหมาะสมในการจัดการกับการทำลายของเอนทิตีเกม


10

ลองนึกภาพโลกของเกมที่มีการโหลดและโหลดเอนทิตีแบบไดนามิกตลอดเวลาฉันจะแสดงว่าเป็นรายการของเอนทิตี แต่สิ่งที่เกี่ยวกับการลบออก?

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

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

ฉันรู้วิธีที่ถูกต้องจะเป็นรายการเช่น List.RemoveAt (whereToRemove); แต่จะเกิดอะไรขึ้นถ้ามีเพียงนิติบุคคลเท่านั้นที่รู้ว่าควรตายเมื่อใด

หรือฉันเพิ่งจะหายไปบางสิ่งบางอย่างและ list container จะรู้เมื่อวัตถุถูกทำลายและลดขนาดตัวมันเอง?

คำตอบ:


10

นี่คือเงื่อนไขของคุณ:

  • วัตถุอื่น ๆ อาจยังคงขึ้นอยู่กับเอนทิตีที่ถูกลบของคุณหลังจากถูกลบออก

  • คุณต้องการให้เอนทิตีระบุการลบของตัวเองเท่านั้น

คุณมีทั้งคู่ไม่ได้ ทำไม? เนื่องจากรหัสในระดับที่สูงกว่าเอนทิตีของคุณเอง (ดูตัวอย่างด้านล่าง) ตัดสินใจว่าจะต้องใช้เอนทิตีนั้นเมื่อใด ดังนั้นรหัสในระดับเดียวกันนั้นเท่านั้นที่สามารถระบุได้ว่าเอนทิตีของคุณเหมาะสมสำหรับการลบหรือไม่

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


ตัวอย่างที่ 1: ไม่มีเหตุการณ์

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

เราตรวจสอบ A เพื่อหาการชนกับ B นั่นคือการชนกัน รับความเสียหาย 50%

เราตรวจสอบ A เพื่อหาการชนกับ C นั่นคือการชนกัน รับความเสียหาย 50% เนื่องจากความเสียหายถึง 0 A กำหนดว่า "ตาย" มันลบตัวเองออกจากรายการ

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

ตัวอย่างที่ 2: กับเหตุการณ์

ตั้งค่าเหมือนเดิม

เราตรวจสอบ A เพื่อหาการชนกับ B นั่นคือการชนกัน รับความเสียหาย 50%

เราตรวจสอบ A เพื่อหาการชนกับ C นั่นคือการชนกัน รับความเสียหาย 50% เนื่องจากความเสียหายถึง 0 A กำหนดว่า "ตาย" มันยิงเหตุการณ์ไปยังรหัสการจัดการเอนทิตีเพื่อพูดว่า "Remove me ASAP" รหัสการจัดการเอนทิตีจะดูที่การอ้างอิงเอนทิตีที่ส่งเป็นส่วนหนึ่งของเหตุการณ์และเก็บการอ้างอิงนั้นในรายการของเอนทิตีที่จะถูกลบออก

เราตรวจสอบ A สำหรับการชนกับ D. ไม่มีการชนกันและการตรวจสอบทำงานได้ดี

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


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

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

PS อย่ากลัวที่จะค้นหาผ่านรายการหลักของคุณเพื่อทำการลบแบบส่วนบุคคล มันเป็นส่วนหนึ่งและส่วนหนึ่งของการจัดการเอนทิตีและแม้แต่รายการใหญ่ ๆ ก็มีแนวโน้มที่จะสำรวจได้อย่างรวดเร็ว - หลังจากทั้งหมดนั่นคือสิ่งที่พวกเขาออกแบบมาเพื่อ


0

คุณกำลังมองหาHashMap / HashTableแน่นอน hashtable คือแผนที่ที่จับคู่กุญแจกับค่าเฉพาะ กุญแจสามารถเป็นอะไรก็ได้ (เช่น Entity ID)


0

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

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

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

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