क्या मुख्य गेम लूप को अनियंत्रित चलाने में कोई नुकसान है?


19

मैं सोच रहा था कि क्या कोई संभावित नुकसान हो सकता है जब मेरा गेम लूप जितनी तेजी से चलता है उतना ही सिस्टम अनुमति देता है?

मेरे पास वर्तमान में एक लूप है, जो नैनोसेकंड में पारित समय को मापकर, गेम लॉजिक चलाता है और बिना किसी समस्या के पूर्वनिर्धारित गति से तर्क प्रदान करता है। वास्तव में लूप में मैं जो भी तर्क करता हूं, उसे प्रत्येक सेकंड में एक निश्चित मात्रा में कॉल किया जाता है।

लूप अपने आप में केवल उतना ही तेज चलता है जितना कि यह पसंद करता है कि मेरी मशीन पर लगभग 11.7 मिलियन लूप एक सेकंड में आता है।

पाश (सरल छद्मकोश):

while(!isGameOver){

 if(canPollInputs){
    pollInputs()
 }

 while(canStepLogic){
    stepLogic()
 }

 if(canRender){
    render()
 }
}

मेरा सवाल मूल रूप से है कि अगर साधारण लूप, यदि इसकी नियंत्रित गति से नहीं चल रहा है, तो क्या सिस्टम को कोई नुकसान पहुंचा सकता है?

संपादित करें: इसका मतलब है कि मेरा तर्क 30 बार (30 tps) सेकंड में चल रहा है, मेरा रेंडर 60 एफपीएस पर चल रहा है, मैं एक सेकंड में 100 बार इनपुट कर रहा हूं और तर्क के साथ सामना करने के लिए कुछ तर्क भी है या अपेक्षा से अधिक समय तक प्रतिपादन करना । लेकिन लूप खुद थ्रोटल नहीं है।

संपादित करें: Thread.sleep()उदाहरण के लिए थ्रॉटल को मुख्य लूप से 250 लूप प्रति सेकेंड तक कम करने का उपयोग करने से घटता है, लेकिन लूप वांछित 250 के बजाय लगभग 570 लूप प्रति सेकंड पर चलता है (जब मैं अपने डेस्कटॉप मशीन पर कोड डालूंगा ..)

संपादित करें: यहां हम जाते हैं, चीजों को स्पष्ट करने के लिए एक कामकाजी जावा गेमेलोप। इसका उपयोग करने के लिए भी स्वतंत्र महसूस करें, लेकिन इसका दावा न करें;)

private void gameLoop() {

    // Time that must elapse before a new run
    double timePerPoll = 1000000000l / targetPPS;
    double timePerTick = 1000000000l / targetTPS;
    double timePerFrame = 1000000000l / targetFPS;
    int maxFrameSkip = (int) ( (1000000000l / MINIMUM_FPS) / timePerTick);

    int achievedPPS = 0;
    int achievedFPS = 0;
    int achievedTPS = 0;

    long timer = TimeUtils.getMillis();

    int loops = 0;

    int achievedLoops = 0;

    long currTime = 0l;
    long loopTime = 0l;

    long accumulatorPPS = 0l;
    long accumulatorTPS = 0l;
    long accumulatorFPS = 0l;

    long lastTime = TimeUtils.getNano();

    while(!isRequestedToStop) {
        currTime = TimeUtils.getNano();
        loopTime = currTime - lastTime;
        lastTime = currTime;

        loops = 0;

        accumulatorPPS += loopTime;
        accumulatorTPS += loopTime;
        accumulatorFPS += loopTime;

        if(accumulatorPPS >= timePerPoll) {
            pollInputs();
            playerLogic();
            achievedPPS++;
            accumulatorPPS -= timePerPoll;
        }

        while(accumulatorTPS >= timePerTick && loops < maxFrameSkip) {
            tick();
            achievedTPS++;
            accumulatorTPS -= timePerTick;
            loops++;
        }

        // Max 1 render per loop so player movement stays fluent
        if(accumulatorFPS >= timePerFrame) {
            render();
            achievedFPS++;
            accumulatorFPS -= timePerFrame;
        }

        if(TimeUtils.getDeltaMillis(timer) > 1000) {
            timer += 1000;
            logger.debug(achievedTPS + " TPS, " + achievedFPS + " FPS, "
                    + achievedPPS + " Polls, " + achievedLoops + " Loops");
            achievedTPS = 0;
            achievedFPS = 0;
            achievedLoops = 0;
        }

        achievedLoops++;
    }
}

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


2
अनिवार्य 'अपना टाइमस्टेप ठीक करें' लिंक: gafferongames.com/game-physics/fix-your-timestep कृपया इसे पढ़ें। यह भी ध्यान दें कि थ्रेड.सलीप () का उपयोग आपके टाइमस्टेप को मज़बूती से करने के लिए नहीं किया जा सकता है क्योंकि ओएस आपके आवेदन पर नियंत्रण को समय की मांगी गई राशि के बाद वापस करने की गारंटी नहीं देता है। (यह भिन्न हो सकते हैं)।
रॉय टी।

हाँ, यह pseudocode के साथ समस्या है। मैंने सबसे अधिक उस गफ़र के बारे में लिखा है जो (वर्तमान में एक डेल्टा कार्यान्वयन पर काम कर रहा है जो मेरे लूप संरचना को पूरक करता है)। अगर मैं Thread.sleep () का उपयोग नहीं कर सकता तो मानक जावा के भीतर और क्या उपलब्ध है?
dot_Sp0T

1
आप आमतौर पर थ्रेड के साथ एक व्यस्त लूप का उपयोग करते हैं। सोलेप (0) और सर्वश्रेष्ठ के लिए आशा करते हैं। गफ़र कुछ लेखों में इस बारे में बहुत सारी बातें करते हैं।
रॉय टी।

खैर यह है कि मूल रूप से मैं क्या कर रहा हूँ, बिना थ्रेड के सो रहा हूँ। सो (0), और मूल रूप से इस सवाल को क्या उकसाया। क्या सिस्टम के लिए एक व्यस्त (सम्मान में व्यस्त नहीं है कि थोड़ा दोहरावदार तर्क भी नीचे फेंक दिया जाता है) लूप में कोई नुकसान है?
dot_Sp0T

कुछ समय पहले, एक बग ने Starcraft II को कुछ शर्तों के तहत ऐसा करने का कारण बनाया। यह वास्तव में कुछ GPU पिघलने समाप्त हो गया। तो हाँ, यह एक अनियंत्रित गेम लूप के लिए बहुत संभव है जिससे नुकसान हो।
मैसन व्हीलर

जवाबों:


35

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

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

इस समस्या को कम करने के लिए, आपको अपने फ्रैमरेट (ग्राफिक और तर्क) को अधिकतम उस सीमा तक सीमित करना चाहिए जो मानव आंख देख सकती है। यह कितना विवादित है और यह एनीमेशन के प्रकार पर निर्भर करता है और यह किस तरह के डिस्प्ले पर दिखाया जाता है, लेकिन अनुमान 40 एफपीएस से लेकर 120 एफपीएस तक हैं। इसका मतलब है कि आपको 20ms और 8ms के बीच प्रत्येक लूप के निष्पादन का न्यूनतम समय निर्धारित करने की आवश्यकता है। एक लूप पुनरावृत्ति तेजी से खत्म होनी चाहिए, sleepशेष टाइमपैन के लिए सीपीयू धागा दें ।


स्पष्टीकरण के लिए धन्यवाद फिलीपींस। मैंने वास्तव में इस तथ्य का उल्लेख किया था कि मैं एक निश्चित एफपीएस पर चल रहा हूं और साथ ही एक सेकंड में केवल एक निश्चित मात्रा में ही मतदान करता हूं। हालांकि इसे स्पष्ट करने की कोशिश करेंगे।
dot_Sp0T

@ dot_Sp0T आपके प्रश्न को संपादित करने के बाद, केवल पहला पैराग्राफ और अंतिम वाक्य आपके मामले के लिए प्रासंगिक हैं। हालाँकि, मैं अपने उत्तर के दूसरे और तीसरे पैराग्राफ को बरकरार रखना चाहूंगा क्योंकि वे दूसरों के लिए मददगार हो सकते हैं।
फिलिप

मैं संभवतः आपके उत्तर को स्वीकार करूंगा क्योंकि पहला पैराग्राफ पूरी तरह से एक उत्तर देता है। क्या आप किसी भी तरह के जवाब के बाकी हिस्सों से अलग करने के लिए मन करेंगे?
dot_Sp0T

डेस्कटॉप पर एक अप्रकाशित सभ्यता 2 खेलें और आप इसे एक समस्या पाएंगे। कम से कम, मैं करता हूं। कंधे उचकाने की क्रिया
corsiKa

1
बैटरी और प्रशंसक विचारों के अलावा, सीपीयू के उपयोग में वृद्धि से अतिरिक्त गर्मी हो सकती है जो असुविधाजनक हो सकती है (जैसे लैपटॉप, एस्प मेरी आरएमबीपी) और यहां तक ​​कि पीसी को बंद करने के लिए नेतृत्व (एस्प पुराने पीसी के धूल वाले कूलर के साथ)। यदि आप सभी कोर 100% चलाते हैं, तो ये कारक अतिरंजित हैं ।
NPSF3000

2

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

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

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


मैं इसके विपरीत ऐसे लोगों को कहना चाहूंगा जो अपनी मशीनों का निर्माण करते हैं, अच्छे प्रशंसकों का उपयोग करते हैं, यहां तक ​​कि वाटरकूलिंग का भी। केवल HTPC या मिनी ITX मामलों में उस हिस्से की सीमाएँ हो सकती हैं। अन्यथा, गरीब लेकिन उत्साही लोग बॉक्स वेंटिरेड का उपयोग करेंगे। जो 100% पर भी पर्याप्त है, गर्म लेकिन ठीक है।
v.oddou

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

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

1

आप घबराना आंदोलन / gameplay नहीं होना चाहिए

दो तरीके हैं जो आप खेल तर्क को लागू कर सकते हैं - एक वास्तविक समय से बंधा हुआ है, या "बदल जाता है" / प्रसंस्करण चरणों की संख्या से बंधा हुआ है। यदि आपके खेल में कोई चीज़ बाईं ओर घूम रही है, तो क्या यह गति भिन्न होगी यदि आपके स्टेपलॉजिक () को 50 बार के बजाय 100 कहा जाता है?

यदि आपका कोड बीता हुआ समय हर जगह स्पष्ट रूप से मानता है और इसे सही ढंग से करता है, तो यह ठीक हो सकता है; लेकिन अगर आपके कोड में ऐसा कुछ है जो 'चरणों' की संख्या पर निर्भर करता है तो आपको अवांछित दुष्प्रभाव होंगे।

सबसे पहले, लगातार चलती रहने वाली चीजों की गति अप्रत्याशित रूप से (प्रोसेसर उपयोग के आधार पर) अलग-अलग होगी, और यह बहुत कष्टप्रद नियंत्रण के लिए बनाता है - यदि खेल अचानक गति बढ़ाता है या धीमा हो जाता है, तो आप एक सटीक पंच या कूद नहीं कर सकते। यहां तक ​​कि बिना किसी 'चिकोटी' वाले गेम के लिए, अगर चीजें सुचारू रूप से नहीं चल रही हैं तो यह कष्टप्रद और चिड़चिड़ा लगता है।

दूसरा, आपको कंप्यूटर की गति के आधार पर चरित्र क्षमताओं के साथ समस्याएं मिल सकती हैं - एक क्लासिक उदाहरण पुराना क्वेक मुद्दा है जहां अधिकतम कूदने की सीमा अनजाने में आपके एफपीएस पर निर्भर थी।

यदि आप कोड को एफपीएस-स्वतंत्र होने का प्रयास करते हैं, तो भी ये समस्याएँ प्रकट हो सकती हैं, गोलाई त्रुटियों का संचय अक्सर ऐसे कीड़े पैदा कर सकता है।


1
जितना मुझे तुम्हारा उत्तर पसंद है उतना ही यह सवाल के लिए प्रासंगिक नहीं है, जैसा कि मैं चिड़चिड़ा आंदोलन / गेमप्ले के बारे में नहीं पूछ रहा हूं, लेकिन नुकसान के बारे में अनियंत्रित लूप (जो किसी भी तर्क या प्रतिपादन या कुछ और को नियंत्रित नहीं करता है)
dot_Sp0T

1

एकमात्र संभावित नुकसान आपकी बिजली की खपत है, इसलिए मोबाइल उपकरणों पर ऐसा न करें। इसके विपरीत, कुछ एम्बेडेड सिस्टम अपना पूरा जीवन एक चीज के इंतजार में लूप में बिताते हैं।

यह पूरी तरह से सामान्य रूप से गेम फ्रेम को यथासंभव सरल रूप से प्रस्तुत करने के लिए उपयोग किया जाता था, कभी-कभी एक टाइमर के बिना भी अलग-अलग सीपीयू गति के लिए गेमप्ले की भरपाई करने के लिए। बुलफ्रॉग का रेसिंग गेम हाय-ऑक्टेन इसका विशेष रूप से बुरा शिकार था, और मुझे संदेह है कि यह Civ2 के पोस्टर का जिक्र है।

यदि आप एक विंडोज सिस्टम या इसी तरह के हैं, तो कम से कम इनपुट प्रतिक्रिया सुनिश्चित करने के लिए मैं आपको कम से कम पोल इनपुट की सलाह दूंगा।


यह टाइमर का सवाल नहीं है, यह एक कालानुक्रम का सवाल है जो मैं कहूंगा, या एक प्रदर्शन काउंटर। एक को कुछ बिंदु पर वास्तविक समय प्राप्त करने की आवश्यकता होती है, और एक मुफ्त लूप पूरी तरह से काम करता है। हालांकि एक टाइमर (नियमित रुकावट के अर्थ में) सामान्य उपयोग में लूप की गति को विनियमित करने का प्रयास कर रहा है। मैं इसे अच्छा नहीं मानता। गेम लूप को विनियमित करने के लिए vsync सिग्नल पर swap/ present/ flipफ़ंक्शन का उपयोग करना बेहतर होता है ।
v.oddou
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.