Ana oyun döngüsünün kontrolsüz çalışmasının herhangi bir zararı var mı?


19

Oyun döngümün sistemin izin verdiği kadar hızlı çalıştığında herhangi bir zarar olup olmadığını merak ediyordum?

Şu anda nanosaniyede geçen zamanı ölçerek, oyun mantığını ve mantığı önceden tanımlanmış hızlarda sorunsuz bir şekilde çalıştıran bir döngü var. Aslında, döngüde yaptığım herhangi bir mantık, her saniye belirli bir miktarda çağrıya saatlenir.

Döngünün kendisi, makinemde saniyede yaklaşık 11,7 milyon döngüye kadar çıktığı kadar hızlı çalışır.

Döngü (basit sahte kod):

while(!isGameOver){

 if(canPollInputs){
    pollInputs()
 }

 while(canStepLogic){
    stepLogic()
 }

 if(canRender){
    render()
 }
}

Benim sorum temelde bu basit döngü, kontrollü bir hızda çalışmıyorsa, sisteme herhangi bir zarar verebilir mi?

Düzenleme: Bu, mantığımın saniyede 30 kez (30 tps) çalıştığı, oluşturucumun 60 fps'de çalıştığı, girişleri saniyede 100 kez yokladım ve ayrıca mantıkla başa çıkmak veya mantık beklenenden daha uzun sürüyor . Ancak döngünün kendisi kısıtlanmaz.

Düzenleme: Thread.sleep()Örneğin kullanarak ana döngü saniyede 250 döngü aşağı Gaz kelebeği bir azalmaya yol açar, ancak döngüler istenen 250 yerine saniyede 570 döngüde çalışır (masaüstü makinemdeyken kod ekler ..)

Düzenleme: İşte başlıyoruz, işleri netleştirmek için çalışan bir java gameloop. Ayrıca kullanmaktan çekinmeyin, ancak size ait olduğunu iddia etmeyin;)

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++;
    }
}

Gördüğünüz gibi, her döngüde neredeyse hiç kod çalıştırılmaz, ancak her zaman ne kadar gerçek zaman geçtiğine bağlı olarak belirli bir seçim vardır. Soru, bu 'işçi döngüsüne' ve bunun sistemi nasıl etkilediğine atıfta bulunmaktır.


2
zorunlu 'zamanınızı düzeltin' bağlantısı: gafferongames.com/game-physics/fix-your-timestep lütfen okuyun. Ayrıca, Thread.Sleep () yönteminin zaman aşımınızı güvenilir bir şekilde kısmak için kullanılamayacağına dikkat edin, çünkü işletim sistemi istenen süreden sonra kontrolü uygulamanıza iade etmeyi garanti etmez. (Değişebilir).
Roy T.

Evet, sahte kodda sorun var. Ben gaffer hakkında ne yazıyor çoğu (şu anda benim döngü yapısını tamamlayan bir delta uygulaması üzerinde çalışıyor). Thread.sleep () kullanamıyorsam, standart Java'da başka neler var?
dot_Sp0T

1
Genellikle Thread.Sleep (0) ile meşgul bir döngü kullanırsınız ve en iyisini umarsınız. Gaffer bunu birkaç makalede çok konuşuyor.
Roy T.

Temelde yaptığım şey, sadece thread.sleep (0), ve aslında bu soruyu provoke eden şeydi. Sistem için meşgul (bu küçük tekrarlayan mantık daraltıldığı için meşgul değil) döngüsünde herhangi bir zarar var mı?
dot_Sp0T

Bir süre önce, bir hata Starcraft II'nin bunu belirli koşullar altında yapmasına neden oldu. Kelimenin tam anlamıyla birkaç GPU'yu eritti. Yani, kontrolsüz bir oyun döngüsünün zarar vermesi çok mümkün.
Mason Wheeler

Yanıtlar:


35

Bir CPU çekirdeğinin her zaman% 100 oranında çalışmasına neden olur. Bu genellikle sisteme zarar vermez . CPU'lar saatlerce% 100 çalışacak şekilde tasarlanmıştır. Ancak bir mobil cihazda pili hızlı bir şekilde tüketir ve cihazı ısıtır, bu da mağaza puanlarınızda bir yıldıza mal olur. Bir masaüstü bilgisayarda bu daha az problemdir, ancak daha fazla kullanıcının elektriğini tüketir, CPU fanının daha hızlı dönmesine neden olur, bu da başka işlemler tarafından kullanılabilecek bazı gürültü ve atık CPU döngülerine neden olabilir. Bunlar kritik kusurlar olmasa da, hala kötü bir stildir, bu yüzden mümkünse onlardan kaçınmalısınız.

Oyun mantık döngünüzün dahili olarak nasıl çalıştığı hakkında hiçbir şey söylemediniz, ancak delta-time yaklaşımını kullandığınızda (yaptığınız her hesaplama, son çağrıdan bu yana geçen zamanı alır), çok küçük delta- zaman değerleri. Bu, her türlü garip davranışa neden olabilecek kayan nokta yanlışlığı ile ilgili problemlerle karşılaşabileceğiniz anlamına gelir. Ayrıca, sistem zamanlayıcının çözünürlüğü genellikle sınırlıdır, bu nedenle mantık döngünüz çok hızlı olduğunda sıfır delta-t değeri elde edebilirsiniz, bu da çarpışma ile sonuçlanan sıfır ile bölünmeye neden olabilir.

Bu sorunu hafifletmek için, kare hızınızı (grafik ve mantık) insan gözünün algılayabileceği maksimum değerle sınırlamalısınız. Bunun ne kadar tartışmalı olduğu ve animasyon türüne ve ne tür bir gösterime bağlı olduğuna bağlıdır, ancak tahminler 40 FPS ila 120 FPS arasında değişir. Bu, 20 ms ve 8 ms arasında her bir döngünün minimum yürütme süresini ayarlamanız gerektiği anlamına gelir. Bir döngü yinelemesi daha hızlı biterse sleep, kalan zaman aralığı için cpu iş parçacığını bırakın .


Açıklama için teşekkürler Philipp. Aslında belirli bir fps ve tps'de koştuğum ve oylamayı saniyede sadece belirli bir kez yaptığımdan bahsetmiştim. Yine de daha açık hale getirmeye çalışacağız.
dot_Sp0T

@ dot_Sp0T Sorunuzda yaptığınız düzenlemeden sonra, yalnızca ilk paragraf ve son cümle davanızla ilgilidir. Ancak cevabımın ikinci ve üçüncü paragrafını saklamak istiyorum çünkü başkalarına yardımcı olabilirler.
Philipp

İlk paragraf mükemmel bir şekilde cevap verdiğinden, muhtemelen cevabınızı da kabul edeceğim. Bir şekilde görsel olarak cevabın geri kalanından ayırmak ister misiniz?
dot_Sp0T

Masaüstünde eşsiz bir Uygarlık 2 oynayın ve bunun bir sorun olduğunu göreceksiniz. En azından öyle. shrug
corsiKa

1
Pil ve fan hususlarına ek olarak, artan CPU kullanımı rahatsız edici olabilecek aşırı ısıya neden olabilir (örn. Dizüstü bilgisayar, esp rMBP) ve hatta bilgisayarın kapanmasına (tozlu soğutuculu esp eski PC'ler) neden olabilir. Tüm çekirdekleri% 100 çalıştırırsanız bu faktörler bıkkın .
NPSF3000

2

CPU döngülerini boşa harcıyorsunuz. Bu, dizüstü bilgisayarlarda, tabletlerde ve telefonlarda daha düşük pil süresi, daha yüksek elektrik faturaları, makine tarafından üretilen daha fazla ısı, daha gürültülü fanlar anlamına gelir. Ayrıca, diğer önemli sistem işlemlerinden (örneğin, pencere sunucusu sarsıntılı olabilir) yemek yiyor olabilirsiniz, bu da oyunu etkileyebilir. Bugünün önleyici çoklu görev sistemlerindeki bazı sistem zamanlayıcılar da çok fazla döngü kullanan uygulamaları cezalandırır, bu nedenle önce hızlı olabilirsiniz, daha sonra sistem tarafından kısıldığınızda aniden garip sarsıntı görürsünüz.

Birçok hardcore oyuncu, fanlarının özelliklerinin kenarındaki sıfırdan özel PC'ler de oluşturur, bu durumda sıcak bir gün ve oyununuzun ürettiği ısı, emniyetlerin makinede tetiklenmesine (en iyi şekilde) neden olabilir ve hatta parçaların aşırı ısınmasına neden olabilir ve ölmek (en kötüde). Hedef kitleniz buysa, her zaman "en üstte" biraz alan bıraktığınızdan emin olmak isteyebilirsiniz.

Son olarak, daha yavaş makineleri olan oyuncuları daha yavaş olanlara göre daha ileriye götüreceğiniz oyun sorunları var. Oyun döngüsünün belirli bir sıklıkta kapatılması ve yalnızca oyunla alakalı olmayan yönler için ek döngülerin kullanılması (daha yüksek kaliteli grafikler, surround ses efektleri veya herhangi bir şey gibi) oyununuzu daha adil hale getirecektir.


Tersine, makinelerini tutkuyla yapan insanlar, su soğutmalı bile iyi fanlar kullanıyor. Yalnızca HTPC veya mini ITX vakalarında bu bölümde sınırlamalar olabilir. Aksi takdirde, yoksul ama meraklıları insanlar ventirad kutusunu kullanacaklar. Bu bile% 100, sıcak ama Tamam yeterli.
v.oddou

Sadece deneyimden tekrar ediyorum. Star Trek Online'a bakarsanız, GUI'lerinde, belirli makinelerin aşırı ısınmasını önlemek için ana döngüsüne sleep () ekleyecek ayrı bir ayarları vardır, bu yüzden Neverwinter ve STO ekleme ihtiyacını gördü. Bu tutkuyu unutmayın! = Beceri. Çok yetenekli ve tutkulu tamirciler var, ancak yeni başlayanlar ve hala öğrenmekte olan diğerleri var ve iyi bir bırakma oranı ile istatistikler, çoğunluk olduklarını söylüyor.
uliwitness

Bu yorumlar sayesinde cevabınızı tekrar okudum. Geçerli noktaları listeliyorsunuz, ancak ne yazık ki soruyu daha hızlı makinelerle daha yavaş makineler tartışmasıyla gerçekten ele almıyorsunuz . Mantık döngüsü (denilen gameloop üçüncü paragrafta) sınırlanır. Soru, giriş çekilirse, mantık hesaplanırsa veya bir çerçeve oluşturuluyorsa, her çalışmayı yeniden değerlendiren omurga döngüsünü
kapatmakla ilgiliydi

1

Gergin hareket / oyun oynamamalısınız

Oyun mantığını gerçek zamanlı olarak uygulamanızın veya "dönüşler" / işleme adımlarının sayısına bağlı olmanın iki yolu vardır. Oyununuzdaki bazı şeyler sola hareket ediyorsa, stepLogic () cihazınıza 50 kez yerine 100 çağrıldıysa hareket farklı mı olacak?

Kodunuz geçen süreyi her yerde açık bir şekilde ele alıp doğru şekilde yapıyorsa, sorun olabilir; ancak kodunuzda "adımların" sayısına bağlı bir şey varsa, istenmeyen yan etkiler elde edersiniz.

Birincisi, sürekli hareket etmesi gereken şeylerin hızı beklenmedik bir şekilde değişecektir (işlemci kullanımına bağlı olarak) ve bu çok can sıkıcı kontroller yapar - oyun aniden hızlanırsa veya yavaşlarsa hassas bir yumruk veya atlama yapamazsınız. Hiç 'seğirme' olmayan oyunlar için bile, işler düzgün hareket etmiyorsa sinir bozucu ve gergin görünüyor.

İkincisi, bilgisayar hızına bağlı olarak karakter yetenekleriyle ilgili sorunlar yaşayabilirsiniz - klasik bir örnek, maksimum atlama aralığının yanlışlıkla fps'nize bağlı olduğu eski Quake sorunudur.

Bu sorunlar kodu fps bağımsız olmaya çalışsanız bile görünebilir, yuvarlama hatalarının birikmesi genellikle bu tür hatalara neden olabilir.


1
Cevabınızı istediğim kadar, bu soru ile ilgili değil, gergin hareket / oyun hakkında değil, kontrolsüz bir döngü (herhangi bir mantık veya render veya başka bir şey kontrol etmeyen) zarar hakkında sys
dot_Sp0T

1

Tek olası zarar güç tüketiminizdir, bu yüzden mobil cihazlarda bunu yapmayın. Tersine, oldukça az sayıda gömülü sistem tüm yaşamlarını bir şeyin gerçekleşmesini bekleyerek bir döngüde geçirir.

Oyun karelerini olabildiğince hızlı, bazen de farklı CPU hızları için oyunu telafi etmek için bir zamanlayıcı bile olmadan oluşturmak tamamen normaldi. Bullfrog'un yarış oyunu Hi-Octane bunun özellikle kötü bir kurbanıydı ve Civ2'den bahseden posterin bundan bahsettiğinden şüpheleniyorum.

Hızlı giriş tepkisi sağlamak için, Windows veya benzeri bir sistemdeyseniz, her geçişte en azından girdileri yoklamanızı öneririm.


Bu bir zamanlayıcı sorunu değil, daha doğrusu söyleyeceğim bir kronometre veya bir performans sayacı meselesi. Bir noktada gerçek zamanı elde etmek gerekir ve ücretsiz bir döngü mükemmel çalışır. Bununla birlikte, bir zamanlayıcı (düzenli kesinti anlamında), genel kullanımda döngü hızını düzenlemeye çalışmaktadır. Bunu iyi düşünmüyorum. Oyun döngüsünü düzenlemek için swap/ present/ flipfonksiyonunun vsync sinyalini beklemek için kullanılması tercih edilir .
v.oddou
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.