2D yan kaydırıcı için “Optimal” oyun döngüsü


14

2D yan kaydırıcının oyun döngüsü için bir "optimal" (performans açısından) düzeni tanımlamak mümkün müdür? Bu bağlamda "oyun döngüsü" kullanıcı girdisini alır, oyun nesnelerinin durumlarını günceller ve oyun nesnelerini çizer.

Örneğin derin bir miras hiyerarşisine sahip bir GameObject temel sınıfına sahip olmak bakım için iyi olabilir ... aşağıdakine benzer bir şey yapabilirsiniz:

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

Ancak bu yaklaşımın performans sorunları yaratabileceğini düşünüyorum.

Öte yandan, tüm oyun nesnelerinin verileri ve işlevleri küresel olabilir. Bu bir bakım baş ağrısı olabilir, ancak en iyi performans gösteren oyun döngüsüne daha yakın olabilir.

Düşüncesi olan var mı? En iyi oyun döngüsü yapısının pratik uygulamalarıyla ilgileniyorum ... harika bir performans karşılığında bakım baş ağrım olsa bile.


Yanıtlar:


45

Örneğin derin bir miras hiyerarşisine sahip bir GameObject temel sınıfına sahip olmak bakım için iyi olabilir ...

Aslında, derin hiyerarşiler sürdürülebilirlik için genellikle sığ olanlardan daha kötüdür ve oyun nesneleri için modern mimari tarz, sığ, kümelenmeye dayalı yaklaşımlara doğru eğilimlidir .

Ancak bu yaklaşımın performans sorunları yaratabileceğini düşünüyorum. Öte yandan, tüm oyun nesnelerinin verileri ve işlevleri küresel olabilir. Bu bir bakım baş ağrısı olabilir, ancak en iyi performans gösteren oyun döngüsüne daha yakın olabilir.

Gösterdiğiniz döngü potansiyel olarak performans sorunlarına sahiptir, ancak sonraki ifadenizde belirtildiği gibi GameObjectsınıfta örnek verilere ve üye işlevlere sahip olduğunuz için değil . Aksine, sorun, oyundaki her nesneye tamamen aynı şekilde davranırsanız , muhtemelen bu nesneleri akıllı bir şekilde gruplandırmamanızdır - muhtemelen bu liste boyunca rastgele dağılmışlardır. Potansiyel olarak, o nesne için güncelleme yöntemine yapılan her çağrı (bu yöntemin global bir işlev olup olmadığı ve nesneye göre dizin verdiğiniz bir tabloda ya da her neyse, örnek veri veya "global veri" olup olmadığı) son döngü yinelemelerindeki güncelleme çağrısından farklı.

Bu, sisteme artan baskıyı arttırabilir, çünkü ilgili işlev bellekte ve belleğin dışında işlevle sayfayı sayfalandırmanız ve talimat önbelleğini daha sık doldurmanız gerekebilir, bu da daha yavaş bir döngüye neden olur. Bunun çıplak gözle (veya bir profil oluşturucuda) gözlemlenip gözlemlenmediği, tam olarak bir "oyun nesnesi" olarak kabul edilen şeye , ortalama kaç tanesinin var olduğuna ve uygulamanızda başka neler olduğuna bağlıdır.

Bileşen yönelimli nesne sistemleri şu anda popüler bir trend olup toplamanın kalıtımdan daha çok tercih edilebileceği felsefesinden yararlanmaktadır . Bu tür sistemler potansiyel olarak bileşenlerin "güncelleme" mantığını bölmenize izin verir (burada "bileşen" kabaca fizik sistemi tarafından işlenen bir nesnenin fiziksel olarak simüle edilmiş kısmını temsil eden şey gibi bazı işlevsellik birimi olarak tanımlanır. ) mümkün olduğunda ve istenirse performans kazancı sağlayabilecek birden fazla iş parçacığına - bileşen türüne göre ayırt edilir. En azından bileşenleri, belirli bir türdeki tüm bileşenler birlikte güncelleyecek şekilde düzenleyebilir ve CPU önbelleğini en iyi şekilde kullanabilirsiniz. Bu tip bir bileşen yönelimli sistemin bir örneği bu yazıda ele alınmıştır .

Bu tür sistemler genellikle yüksek oranda ayrıştırılır, bu da bakım için bir nimettir.

Veri yönelimli tasarım ilgili bir yaklaşımdır - bu, öncelikle öncelikli olarak nesnelerin gerekli verilerinin etrafına yönlendirilmesiyle ilgilidir, böylece bu veriler toplu olarak etkili bir şekilde işlenebilir (örneğin). Bu genellikle aynı amaç kümesi için kullanılan verileri bir arada tutmaya ve bir anda çalıştırmaya çalışan bir kuruluş anlamına gelir. OO tasarımı ile temel olarak uyumsuz değildir ve bu konuda GDSE'de bu konuda biraz sohbet edebilirsiniz .

Aslında, oyun döngüsüne orijinaliniz yerine daha uygun bir yaklaşım olacaktır.

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

daha çok benzeyen

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

Böyle bir dünyada, her GameObjectkendi için bir işaretçi veya başvurusuna sahip olabilir PhysicsDataya Scriptya RenderData, sen bireysel bazda nesnelerle etkileşim gerekebilir durumlarda, ama asıl PhysicsData, Scripts, RenderData, vesaire hepsi kendi alt sistemleri ait olacak (fizik simülatörü, komut dosyası barındırma ortamı, oluşturucu) ve yukarıda belirtildiği gibi toplu olarak işlenir.

Öyle çok önemli bu yaklaşım sihirli mermi değildir ve (genellikle daha iyi olmasına rağmen her zaman performans artışı vermez unutmayın tasarım derin bir miras ağacın yerine). Özellikle çok az nesneniz veya güncellemeleri etkili bir şekilde paralelleştiremeyeceğiniz çok fazla nesneniz varsa, temelde hiçbir performans farkı fark edemezsiniz.

Ne yazık ki, en uygun olan sihirli bir döngü yoktur - her oyun farklıdır ve farklı şekillerde performans ayarlaması gerekebilir. Bu nedenle, internette rastgele bir adamın tavsiyesini almadan körü körüne gitmeden önce şeyleri ölçmek (profil) çok önemlidir.


5
Tanrım, bu harika bir cevap.
Raveline

2

Oyun nesnesi programlama tarzı daha küçük projeler için uygundur.Proje gerçekten çok büyüdükçe, derin miras hiyerarşisi ile karşılaşacaksınız ve Oyun-nesne tabanı gerçekten ağır olacak!

Örnek olarak ... Diyelim ki Konum (x ve y için), displayObject (bu bir çizim elemanı ise görüntüyü ifade eder), genişlik, yükseklik vb.

Şimdi daha sonra bir animasyon durumuna sahip olacak bir alt sınıf eklememiz gerekirse, büyük olasılıkla 'animasyon kontrol kodu' (şu ankiAnimationId, bu animasyon için kare sayısı, vb.) nesnelerde animasyon olacaktır.
Daha sonra statik (herhangi bir animasyon içermeyen) katı bir gövde eklemek istiyorsanız, 'animasyon kontrol kodunun GameObject Base'in güncelleme fonksiyonunda (animasyonun orada olup olmadığını kontrol etmenize rağmen) kontrol etmeniz gerekir. ..it önemlidir!) Bunun aksine, Bileşen Tabanlı Yapı'yı izlerseniz, nesnenize bir 'animasyon Kontrol Bileşeni' eklenir. Gerekirse onu eklersiniz. Statik bir gövde için bu bileşeni eklemezsiniz. şekilde, gereksiz kontrollerden kaçınabiliriz.

Bu nedenle, stili seçme seçimi projenin boyutuna bağlıdır.GameObject yapısının daha küçük projeler için ustalaşması kolaydır.


@Josh Petrie - Gerçekten harika bir cevap!
Ayyappa

!: @Josh Petrie - faydalı linkler ile Gerçekten iyi cevap (P sry yayınınızın yanında bu yorumu yerleştirmek nasıl bilmiyorum)
Ayyappa

Normalde cevabımın altındaki "yorum ekle" bağlantısını tıklayabilirsiniz, ancak bu geçerli olduğunuzdan daha fazla itibar gerektirir (bkz. Gamedev.stackexchange.com/privileges/comment ). Ve teşekkürler!
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.