กำจัดวัตถุที่ตายแล้วในเกมได้อย่างมีประสิทธิภาพหรือไม่?


10

ฉันกำลังใช้ลูป for หรือ foreach ลูป (ไม่สำคัญ) เพื่อวนลูปผ่านวัตถุทั้งหมดของฉันเมื่อพวกเขาต้องการการปรับปรุงหรือวาด อย่างไรก็ตามเมื่อวัตถุถูกฆ่าตายฉันต้องการให้มันถูกลบออกจากคอลเลกชันอีกครั้ง

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

มีวิธีที่ดีกว่าในการทำเช่นนี้?



2
เรื่องนี้ไม่มีอะไรเกี่ยวข้องกับการเก็บขยะแม้จะมีการใช้คำว่า "ขยะ" ในชื่อเรื่องและคำตอบจนถึงที่ได้กล่าวถึง. NET Garbage Collector
Andrew Russell

ฉันใช้เสรีภาพในการเปลี่ยนคำว่า "ขยะ" เป็น "ตาย" เพื่อป้องกันความสับสนกับ. NET garbage collector
ไม่เป็นไร

โอ้ฉันรู้เรื่องนั้น บทความการเก็บขยะยังคงมีความเกี่ยวข้องเนื่องจากอาจเล่นเป็นสิ่งที่คุณทำกับวัตถุที่ตายแล้ว เช่นเศษซากที่ตายแล้ว? ยกเลิกการเชื่อมโยงจากทุกสิ่งรีเซ็ตเป็นค่าเริ่มต้นวางกลับในฝากข้อมูลขยะ
doppelgreener

คำตอบ:


11

ก่อนอื่น: คำศัพท์ ถ้าคุณพูดว่า "รายการขยะ" ผู้คนจะคิดว่าคุณกำลังพูดถึงตัวเก็บขยะ ลองเรียกมันว่า "รายการที่ตายแล้ว"

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

for(int i = list.Count-1; i >= 0; --i)
{
    if(list[i].IsDead)
        list.RemoveAt(i);
}

โปรดทราบว่าคุณย้ำไปข้างหลัง คุณสามารถลบรายการในขณะที่วนไปข้างหน้า แต่ก็ Messier gotoและต้องใช้ foreachคุณไม่สามารถทำมันได้ด้วย

คุณสามารถทำการลบแยกจากลูปการอัพเดตของคุณ หรือคุณสามารถรวมมันเข้าไปในลูปการอัปเดตของคุณ ทำRemoveAtที่ส่วนท้ายของลูปเสมอ - หลังจากจุดนั้นในลูปlist[i]ไม่สามารถพิจารณาว่าใช้ได้ (มันจะใช้ได้อีกครั้งในการทำซ้ำครั้งถัดไป)

โปรดทราบว่าแต่ละวัตถุมีการIsDeadตั้งค่าสถานะของตนเอง(ถ้าคุณใช้รูปแบบการกำจัดคุณสามารถทำได้IsDisposed) - คุณไม่จำเป็นต้องรักษา "รายการที่ตายแล้ว" เลย

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

หากคุณมีคอลเล็กชันนอกเหนือจาก a List<>ดังนั้นการลบไอเท็มที่ตายแล้วออกจากคอลเล็กชันนั้นอาจยังเกี่ยวข้องกับการสร้างรายการที่ตายแล้ว (เนื่องจากการลบในระหว่างการทำซ้ำอาจไม่สามารถทำได้) ในความคิดของฉันมันดีกว่าการออกแบบเพื่อสร้างรายการตายก่อนที่มันจะถูกใช้โดยวนซ้ำคอลเล็กชันที่ค้นหาIsDeadธงแทนที่จะพยายามรักษารายการเมื่อวัตถุถูกฆ่า

เมื่อคุณเสร็จสิ้นรายการที่ตายแล้วคุณควรClear()ใช้แล้วเก็บไว้รอบ ๆ เพื่อนำมาใช้อีกครั้งในภายหลัง


ดังนั้นรูปแบบที่ใช้แล้วทิ้งถือว่ามีประสิทธิภาพมากกว่าหรือไม่
Jonathan Connell

@ โจนาธาน: ฉันไม่เข้าใจคำถามของคุณ IsDeadรูปแบบเป็นหน้าที่IsDisposedเหมือนกับ การใช้ความหมายหมายIsDeadถึงว่าคุณกำลังรักษารายการวาด / อัปเดตของวัตถุเหล่านี้ที่จะมีการลบรายการที่ตายแล้วออกจากวัตถุนั้นในภายหลัง รูปแบบการกำจัดไม่ได้หมายความว่า ยิ่งไปกว่านั้นรูปแบบการกำจัดไม่ได้หมายความว่าคุณอาจมีทรัพยากรที่ไม่มีการจัดการที่วัตถุนั้น (ซึ่งโดยปกติจะไม่เหมาะสมสำหรับวัตถุการเล่นเกม)
Andrew Russell

คุณสามารถทำได้ด้วย foreach ด้วยการใช้ reverse
shinzou

0

99.9% ของเวลาผู้เก็บขยะ (GC) จะดูแลทุกอย่างโดยไม่ยุ่งยาก เพียงแค่ปล่อยให้มันทำงานเมื่อคุณลบ / ลบวัตถุเหล่านั้น มีเวลาแฝงในการล้างข้อมูลที่ขึ้นอยู่กับปัจจัยหลายประการ (จำนวนหน่วยความจำที่ได้รับมอบหมายเป็นจำนวนมาก) แต่โดยทั่วไปคุณไม่จำเป็นต้องรู้เกี่ยวกับสิ่งนั้น มันออกแบบมาเพื่อทำงาน เหตุผลใดที่คุณใช้ C # ไม่ใช่ C

โดยทั่วไปแล้วประสิทธิภาพของ GC ไม่ต้องกังวลกับตัวเองมากจนเกินไปเว้นแต่คุณจะรู้ (ผ่านการทำโปรไฟล์) ว่ามันกำลังสร้างคอขวด - นี่เป็นเพียงเกมที่ต้องการมากโดยทั่วไป หากเป็นกรณีนี้ให้ดูที่ GC.Collect () และข้อผิดพลาดต่างๆของมันดังนั้นคุณจะรู้ว่าเมื่อใดที่เหมาะสมที่จะใช้ ฉันแนะนำ googling "force gc xna" มีวัสดุมากมายอยู่ข้างนอก


ดังนั้นหากฉันมีรายการที่ฉันใช้ในการโทรอัปเดต () ทุกครั้งองค์ประกอบทั้งหมดในนั้นที่องค์ประกอบเป็น "โมฆะ" จะถูกล้างโดยอัตโนมัติและลบออกหรือไม่
Mathias Lykkegaard Lorenzen

@Mathias ไม่เห็นความคิดเห็นของฉันในคำถามของคุณ ตัวรวบรวมขยะจะไม่แก้ไขสิ่งใดที่คุณยังคงสามารถเข้าถึงได้ - รวมถึงคอลเล็กชันและเนื้อหาของมัน
Andrew Russell

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