एक गेम में मृत वस्तुओं से प्रभावी ढंग से छुटकारा पाना?


10

मैं अपने सभी ऑब्जेक्ट्स के माध्यम से लूप या फॉरच लूप (कोई फर्क नहीं पड़ता) का उपयोग कर रहा हूं, जब उन्हें अद्यतन या तैयार करने की आवश्यकता होती है। हालांकि, जब कोई वस्तु मारी जाती है, तो मैं चाहता हूं कि इसे फिर से संग्रह से हटा दिया जाए।

मैं ऑब्जेक्ट को एक मृत-ऑब्जेक्ट सूची में जोड़कर ऐसा करता हूं, और फिर, जब सब कुछ खींचा और अपडेट किया गया है, तो मैं इस सूची में सब कुछ से गुजरता हूं, साथ ही मूल स्रोत से सूची में वस्तुओं को हटा रहा हूं।

क्या ऐसा करने का कोई बेहतर तरीका है?



2
शीर्षक में "कचरा" शब्द के उपयोग और अब तक के उत्तरों के बावजूद इसका वास्तव में कचरा संग्रह से कोई लेना-देना नहीं है।
एंड्रयू रसेल

मैंने .NET कचरा कलेक्टर के साथ भ्रम को रोकने के लिए "कचरा" शब्द को वास्तव में "मृत" करने के लिए स्वतंत्रता ली।
नेवरमाइंड

ओह मैं इसके बारे में पता कर रहा हूँ। कचरा संग्रह लेख अभी भी प्रासंगिक है क्योंकि यह उन मृत वस्तुओं के साथ क्या खेल सकता है। जैसे मृत मलबे? इसे सब कुछ से अनलिंक करें, इसे डिफ़ॉल्ट पर रीसेट करें, मलबे की बाल्टी में वापस रखें।
डोपेलग्रेनेर

जवाबों:


11

सबसे पहले: शब्दावली। यदि आप "कचरा सूची" कहते हैं, तो लोग सोचेंगे कि आप कचरा संग्रहकर्ता के बारे में बात कर रहे हैं। चलो इसे "मृत सूची" कहते हैं।

जैसा कि आपने शायद खोज लिया है, इसलिए आपका प्रश्न, आप किसी संग्रह से आइटम नहीं निकाल सकते हैं जब आप इसके माध्यम से पुनरावृत्ति कर रहे हैं। यदि आपका संग्रह List<>आइटम निकालने का सबसे सरल तरीका है, तो यह है:

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

ध्यान दें कि आप पीछे की ओर पुनरावृति करते हैं । आगे पुनरावृति करते समय आप आइटम निकाल सकते हैं, लेकिन यह गड़बड़ है और इसके लिए आवश्यकता है goto। आप इसके साथ नहीं कर सकते foreach

आप या तो अपने अपडेट लूप से अलग से निष्कासन कर सकते हैं। या आप इसे अपने अपडेट लूप में मर्ज कर सकते हैं। हमेशा RemoveAtलूप के अंत में करें - लूप में उस बिंदु के बाद, list[i]इसे वैध नहीं माना जा सकता है (यह अगले पुनरावृत्ति पर फिर से वैध हो जाता है)।

ध्यान दें, यह भी कि प्रत्येक वस्तु का अपना एक IsDeadध्वज होता है (यदि आप निपटान पैटर्न का उपयोग कर रहे हैं, तो आप इसे बना सकते हैं IsDisposed) - आपको वास्तव में "मृत सूची" को बनाए रखने की आवश्यकता नहीं है।

प्रत्येक आइटम पर एक ध्वज का उपयोग करना प्रदर्शन के लिए बेहतर है, क्योंकि आप हटाने के लिए सूची के माध्यम से खोज करने से बचते हैं। और यह डिजाइन के लिए भी बेहतर है - इसका मतलब है कि प्रत्येक वस्तु आसानी से जांच सकती है कि क्या यह मर चुका है - इसलिए आप गलती से इस पर कोई भी तरीका नहीं कहते हैं (यदि ये ऑब्जेक्ट डिस्पोजेबल पैटर्न को लागू कर रहे हैं, तो वे ObjectDisposedExceptionइस मामले में फेंक सकते हैं )।

यदि आपके पास एक के अलावा अन्य संग्रह है List<>, तो उस संग्रह से मृत वस्तुओं को हटाने से अभी भी एक मृत सूची का निर्माण शामिल हो सकता है (जैसा कि पुनरावृत्ति के दौरान हटाना संभव नहीं हो सकता है)। मेरी राय में, यह अच्छा है, डिजाइन-वार, मृत सूची बनाने से पहले इसे उपयोग करने से पहले, IsDeadझंडे की तलाश में संग्रह पर पुनरावृत्ति करके , बल्कि सूची को बनाए रखने की कोशिश कर के रूप में वस्तुओं को मार दिया जाता है।

एक बार जब आप एक मृत सूची के साथ समाप्त हो जाते हैं, तो आपको Clear()इसे करना चाहिए , और फिर बाद में इसे फिर से उपयोग करने के लिए चारों ओर रखें।


तो डिस्पोजेबल पैटर्न को और अधिक 'प्रभावी' माना जाता है?
जोनाथन कॉननेल

@ जोनाथन: मैं आपके सवाल को नहीं समझता। IsDeadपैटर्न है कार्यात्मक के समान IsDisposed। शब्दार्थ का IsDeadअर्थ है कि आप इन वस्तुओं की एक ड्रा / अपडेट सूची बनाए रख रहे हैं जिसमें बाद में इसे हटाए गए मृत आइटम होंगे। निपटान पैटर्न का मतलब यह नहीं है कि। इसके अलावा, निपटान पैटर्न का मतलब यह है कि आपके पास उस वस्तु (जो आमतौर पर गेमप्ले ऑब्जेक्ट्स के लिए उपयुक्त नहीं है) द्वारा आयोजित अप्रबंधित संसाधन हो सकते हैं।
एंड्रयू रसेल

आप इसे रिवर्स उपयोग करने के साथ फोरच के साथ कर सकते हैं।
19

0

99.9% समय, कचरा संग्रहकर्ता (जीसी) बिना किसी परेशानी के सब कुछ ध्यान रखेगा। जैसे ही आपने उन ऑब्जेक्ट्स को डिलीट / nulled किया है, बस इसे अपना काम करने दें। क्लीनअप में एक विलंबता होती है जो कई कारकों पर निर्भर करती है (उदाहरण के लिए मेमोरी के कितने ब्लॉक असाइन किए गए हैं) लेकिन आपको आमतौर पर इसके बारे में जानने की जरूरत नहीं है, अकेले इसके बारे में चिंता करें। यह सिर्फ काम करने के लिए बनाया गया है। जो एक कारण है कि आप C # का उपयोग कर रहे हैं और C का नहीं।

सामान्य रूप से रे GC प्रदर्शन, अपने आप पर तब तक चिंता न करें जब तक आपको पता न चले (प्रोफाइलिंग के माध्यम से) कि यह एक अड़चन पैदा कर रहा है - यह केवल आम तौर पर काफी मांग वाले खेलों में है। यदि ऐसा है, तो GC.Collect (), और इसके विभिन्न नुकसानों पर गौर करें, ताकि आप जान सकें कि इसका उपयोग कब करना उचित है। मैं सुझाव देता हूं कि "बल gc xna" पर जाएं, वहां बहुत सारी सामग्री है।


इसलिए अगर मेरे पास एक सूची है जो मैं अपने अपडेट () कॉल में हर बार उपयोग कर रहा हूं, तो इसमें सभी तत्व जहां तत्व "नल" है वह स्वचालित रूप से साफ हो जाएगा, और हटा दिया जाएगा?
मथियास लिकेगार्ड लोरेनजेन

@ माथिया सं। अपने प्रश्न पर मेरी टिप्पणी देखें। कचरा संग्रहकर्ता कुछ भी संशोधित नहीं करेगा जिसे आप अभी भी एक्सेस कर सकते हैं - जिसमें आपका संग्रह और इसकी सामग्री शामिल है।
एंड्रयू रसेल

1
सवाल नहीं है कुछ भी शब्द "कचरा" की दुर्भाग्यपूर्ण पसंद को छोड़कर, जीसी से कोई लेना देना।
नेवरमाइंड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.