2 डी साइड-स्क्रोलर के लिए "इष्टतम" गेम लूप


14

क्या 2 डी साइड-स्क्रॉलर के गेम लूप के लिए "प्रदर्शन" (प्रदर्शन के संदर्भ में) लेआउट का वर्णन करना संभव है? इस संदर्भ में "गेम लूप" उपयोगकर्ता इनपुट लेता है, गेम ऑब्जेक्ट की स्थिति को अपडेट करता है और गेम ऑब्जेक्ट को ड्रॉ करता है।

उदाहरण के लिए एक गहरी विरासत वंशानुक्रम के साथ एक गेम ऑबजेक्ट बेस क्लास रख-रखाव के लिए अच्छा हो सकता है ... आप निम्न की तरह कुछ कर सकते हैं:

foreach(GameObject g in gameObjects) g.update();

हालाँकि मुझे लगता है कि यह दृष्टिकोण प्रदर्शन के मुद्दे बना सकता है।

दूसरी ओर सभी खेल वस्तुओं का डेटा और कार्य वैश्विक हो सकते हैं। जो एक रखरखाव सिरदर्द होगा, लेकिन एक बेहतर प्रदर्शन करने वाले गेम लूप के करीब हो सकता है।

कोई विचार? मैं इष्टतम गेम लूप संरचना के पास के व्यावहारिक अनुप्रयोगों में रुचि रखता हूं ... भले ही मुझे शानदार प्रदर्शन के बदले रखरखाव सिरदर्द मिल जाए।


जवाबों:


45

उदाहरण के लिए एक गहरी विरासत पदानुक्रम के साथ एक GameObject बेस क्लास रखने से रखरखाव के लिए अच्छा हो सकता है ...

दरअसल, गहरी पदानुक्रम आम तौर पर उथले लोगों की तुलना में बनाए रखने के लिए बदतर होती हैं, और गेम ऑब्जेक्ट्स के लिए आधुनिक वास्तुशिल्प शैली उथले, एकत्रीकरण-आधारित दृष्टिकोण की ओर रुझान कर रही है

हालाँकि मुझे लगता है कि यह दृष्टिकोण प्रदर्शन के मुद्दे बना सकता है। दूसरी ओर सभी खेल वस्तुओं का डेटा और कार्य वैश्विक हो सकते हैं। जो एक रखरखाव सिरदर्द होगा, लेकिन एक बेहतर प्रदर्शन करने वाले गेम लूप के करीब हो सकता है।

आपके द्वारा संभावित रूप से दिखाए गए लूप में प्रदर्शन के मुद्दे हैं, लेकिन नहीं, जैसा कि आपके बाद के बयान से निहित है, क्योंकि आपके पास GameObjectकक्षा में डेटा और सदस्य फ़ंक्शन हैं । इसके बजाय, समस्या यह है कि यदि आप खेल में प्रत्येक वस्तु को ठीक उसी के समान मानते हैं , तो आप शायद उन वस्तुओं को समझदारी से समूहबद्ध नहीं कर रहे हैं - वे संभावित रूप से उस सूची में लगभग बिखरे हुए हैं। संभावित रूप से, फिर, उस ऑब्जेक्ट के लिए अपडेट विधि के लिए प्रत्येक कॉल (चाहे वह विधि एक वैश्विक फ़ंक्शन हो या नहीं, और ऑब्जेक्ट की तुलना में इंस्टेंस डेटा या "वैश्विक डेटा" किसी तालिका में चारों ओर तैर रहा हो, जो आप या जो कुछ भी अनुक्रमित कर रहे हैं) अंतिम लूप पुनरावृत्तियों में अद्यतन कॉल से अलग।

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

घटक-उन्मुख ऑब्जेक्ट सिस्टम अभी एक लोकप्रिय प्रवृत्ति है, इस दर्शन का लाभ उठाते हैं कि एकत्रीकरण विरासत के लिए बेहतर है । ऐसी प्रणालियां संभावित रूप से आपको घटकों के "अपडेट" तर्क को विभाजित करने की अनुमति देती हैं (जहां "घटक" को मोटे तौर पर कार्यक्षमता की कुछ इकाई के रूप में परिभाषित किया जाता है, जैसे कि वह चीज जो किसी वस्तु के भौतिक-सिम्युलेटेड हिस्से का प्रतिनिधित्व करती है, जिसे भौतिकी प्रणाली द्वारा संसाधित किया जाता है। ) कई थ्रेड्स पर - घटक प्रकार द्वारा भेदभाव - यदि संभव हो और वांछित, जिसका प्रदर्शन लाभ हो सकता है। बहुत कम से कम आप उन घटकों को व्यवस्थित कर सकते हैं जो किसी दिए गए प्रकार के सभी घटकों को एक साथ अपडेट करते हैं , जिससे सीपीयू के कैश का इष्टतम उपयोग होता है। इस तरह के घटक-उन्मुख प्रणाली का एक उदाहरण इस धागे में चर्चा की गई है

इस तरह की प्रणालियों को अक्सर अत्यधिक खराब कर दिया जाता है, जो रखरखाव के लिए भी एक वरदान है।

डेटा-उन्मुख डिज़ाइन एक संबंधित दृष्टिकोण है - यह पहली प्राथमिकता के रूप में वस्तुओं के लिए आवश्यक डेटा के आसपास खुद को उन्मुख करने के बारे में है, ताकि डेटा को थोक में प्रभावी रूप से संसाधित किया जा सके (उदाहरण के लिए)। यह आमतौर पर एक संगठन का अर्थ है जो एक ही उद्देश्य के क्लस्टर के लिए उपयोग किए गए डेटा को एक साथ रखने और एक ही बार में संचालित करने का प्रयास करता है। यह ओओ डिजाइन के साथ मौलिक रूप से असंगत नहीं है, और आप इस सवाल पर जीडीएसई में विषय पर कुछ बकबक पा सकते हैं ।

वास्तव में, गेम लूप के लिए एक अधिक इष्टतम दृष्टिकोण आपके मूल के बजाय होगा

foreach(GameObject g in gameObjects) g.update();

कुछ और पसंद है

ProcessUserInput();
UpdatePhysicsForAllObjects();
UpdateScriptsForAllObjects();
UpdateRenderDataForAllObjects();
RenderEverything();

इस तरह के एक दुनिया में, प्रत्येक GameObjectअपने स्वयं के लिए एक सूचक या संदर्भ हो सकता है PhysicsDataया Scriptया RenderData, जिन मामलों में आप एक व्यक्तिगत आधार पर वस्तुओं के साथ बातचीत करने के लिए आवश्यकता हो सकती है, लेकिन के लिए वास्तविक PhysicsData, Scripts, RenderData, वगैरह सब अपने-अपने उप के स्वामित्व में किया जाएगा (भौतिकी सिम्युलेटर, स्क्रिप्ट होस्टिंग वातावरण, रेंडरर) और थोक में संसाधित जैसा कि ऊपर संकेत दिया गया है।

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

दुर्भाग्य से, ऐसा कोई जादू का लूप नहीं है जो सबसे इष्टतम है - हर गेम अलग है और अलग-अलग तरीकों से प्रदर्शन ट्यूनिंग की आवश्यकता हो सकती है। इसलिए इंटरनेट पर कुछ यादृच्छिक आदमी की सलाह लेने से पहले आँख बंद करके (प्रोफ़ाइल) चीजों को मापना बहुत महत्वपूर्ण है।


5
अच्छा स्वामी, यह एक महान जवाब है।
Raveline

2

प्रोग्रामिंग की गेम-ऑब्जेक्ट शैली छोटी परियोजनाओं के लिए ठीक है। परियोजना वास्तव में बहुत बड़ी हो जाती है आप गहरी विरासत पदानुक्रम के साथ समाप्त हो जाएंगे और गेम-ऑब्जेक्ट आधार वास्तव में भारी हो जाएगा!

एक उदाहरण के रूप में ... मान लीजिए कि आपने न्यूनतम विशेषताओं के साथ गेम-ऑब्जेक्ट बेस बनाना शुरू कर दिया है, स्थिति (एक्स और वाई के लिए), डिस्प्लेऑबजेक्ट (यह छवि को संदर्भित करता है यदि इसका एक ड्राइंग तत्व है), चौड़ाई, ऊंचाई आदि ...

अब बाद में अगर हमें एक उप वर्ग को जोड़ने की आवश्यकता है, जिसमें एक एनीमेशन राज्य होगा, तो आप शायद 'एनीमेशन नियंत्रण कोड' (जैसे currentAnimationId, इस एनीमेशन के लिए फ़्रेमों की संख्या, आदि) को स्थानांतरित करते हैं।) इस विचार में GameObjectBase के लिए कि अधिकांश वस्तुओं में एनीमेशन होगा।
बाद में यदि आप एक कठोर शरीर जोड़ना चाहते हैं जो स्थिर है (जिसमें कोई एनीमेशन नहीं है), तो आपको गेमऑब्जेक्ट बेस के अपडेट फ़ंक्शन को 'एनीमेशन कंट्रोल कोड'इन की जांच करने की आवश्यकता है (इसकी जांच करें कि क्या एनीमेशन है या नहीं। .. यह मायने रखता है!) इसके विपरीत यदि आप घटक आधारित संरचना का पालन करते हैं, तो आपके पास एक 'एनीमेशन कंट्रोल कंपोनेंट' होगा जो आपकी वस्तु से जुड़ा होगा। यदि आपको इसकी आवश्यकता है तो आप इसे संलग्न कर लेंगे। एक स्थैतिक निकाय के साथ आप उस घटक को संलग्न नहीं करेंगे। यह जिस तरह से, हम आवश्यक जांच से बच सकते हैं।

तो, शैली चुनने का चयन परियोजना के आकार पर निर्भर करता है। GameObject संरचना केवल छोटी परियोजनाओं के लिए मास्टर करना आसान है। हालांकि यह थोड़ा मदद करता है।


@ जोश पेट्री - वास्तव में एक महान जवाब!
अयप्पा

@ जोश पेट्री - उपयोगी लिंक्स के साथ वास्तव में अच्छा जवाब! (Sry पता नहीं कैसे इस टिप्पणी को अपनी पोस्ट के बगल में रखें: P)
अय्यप्पा

आप मेरे जवाब के तहत, सामान्य रूप से "टिप्पणी जोड़ें" लिंक पर क्लिक कर सकते हैं, लेकिन इसके लिए आपको वर्तमान की तुलना में अधिक प्रतिष्ठा की आवश्यकता है (देखें gamedev.stackexchange.com/privileges/comment )। और धन्यवाद!
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.