Oyun Tasarımında Etkinlik Başına Mesajlaşma ve Çerçeve Başına İşlev Çağrıları


11

Geleneksel oyun tasarımı bunu bildiğimiz gibi, kullanır biçimlilik ve sanal fonksiyonlar güncelleme oyun durumlarını nesneleri için. Başka bir deyişle, aynı sanal işlevler kümesi, oyundaki her nesne üzerinde düzenli (ör: kare başına) aralıklarla çağrılır.

Son zamanlarda, oyun nesnelerinin durumlarını güncellemek için başka bir olay güdümlü mesajlaşma sisteminin olduğunu keşfettim . Burada, nesneler genellikle çerçeve başına güncellenmez. Bunun yerine, oldukça verimli bir olay mesajlaşma sistemi oluşturulur ve oyun nesneleri yalnızca geçerli olay mesajı alındıktan sonra güncellenir.

Olay Odaklı Oyun Mimarisi iyi tanımlanmıştır: Mike McShaffry tarafından Komple Oyun Kodlama .

Aşağıdaki sorularla ilgili yardım isteyebilir miyim:

  • Her iki yaklaşımın da avantajları ve dezavantajları nelerdir?
  • Biri diğerinden daha iyi nerede?
  • Etkinlik odaklı oyun tasarımı evrensel ve tüm alanlarda daha mı iyi? Bu nedenle mombile platformlarında bile kullanılması tavsiye edilir mi?
  • Hangisinin daha verimli ve hangisinin geliştirilmesi daha zor?

Açıklığa kavuşturmak gerekirse, sorum polimorfizmi bir oyun tasarımından tamamen kaldırmakla ilgili değil. Ben sadece farkı anlamak ve oyun durumunu güncellemek için sanal işlevlere düzenli (çerçeve başına) çağrılar vs olay güdümlü mesajlaşma kullanarak faydalanmak istiyorum.


Örnek: Bu soru burada biraz tartışmaya neden oldu, bu yüzden size örnek sunmama izin verin: MVC'ye göre, oyun motoru üç ana bölüme ayrılmıştır:

  1. Uygulama Katmanı (Donanım ve İşletim Sistemi iletişimi)
  2. Oyun Mantığı
  3. Oyun Görünümü

Bir yarış oyununda, Oyun Görünümü, ekranı mümkün olan en kısa sürede, en az 30 kare / saniye olarak oluşturmaktan sorumludur. Game View, oyuncunun girdisini de dinler. Şimdi bu olur:

  • Oyuncu yakıt pedalına% 80 basar
  • GameView "Araba 2 Yakıt Pedalı% 80'e Basıldı" mesajını oluşturur ve Game Logic'e gönderir.
  • Game Logic mesajı alır, değerlendirir, yeni arabanın konumunu ve davranışını hesaplar ve GameView için aşağıdaki mesajları oluşturur: "Car 2 Fuel Pedal Draw 80% Press", "Car 2 Sound Acceleration", "Car 2 Coordinates X, Y" .. .
  • GameView mesajları alır ve buna göre işler

nerede buldun bazı bağlantılar veya referans? Bu yaklaşımı bilmiyorum (ama genel olarak oldukça iyi tasarım desenini biliyorum ve genel olarak nesne yönlendirme ilkelerinin iyi bir şekilde kullanılmasını öneriyorum), ancak olay tabanlı olanın daha iyi olduğunu düşünüyorum .. ağ sistemlerindeki evrimi düşünün: zamanuyumsuz çağrılara çağırma .. hesaplamalarda ve soyutlama düzeyinde optimize edilmiştir
nkint

Merhaba Nkint, yorumunuz için teşekkür ederim. Temelde olay güdümlü iletişimi ve sanal işlevlere yapılan çağrıları karşılaştırmak istedim. Sorumu biraz değiştireceğim. Btw, oyun tasarım desenleri içeren bu bağlantıya bir göz atın: gameprogrammingpatterns.com .
Bunkai.Satori

5
Belki aptal oluyorum, ama nasıl bir mesajlaşma sistemi çalışması yapacağız olmadan biçimlilik kullanarak? Olay alıcı arayüzünüzü tanımlamak için bir tür temel sınıfa (soyut veya başka türlü) ihtiyacınız olmayacak mı? (Düzenleme: doğru yansıması olan bir dilde çalışmadığınızı varsayarsak.)
Tetrad

2
Ayrıca, verimlilik uygulama ayrıntılarıyla büyük ölçüde bağlantılı olacaktır. "Hangisinin daha verimli" olduğunu, şu anki haliyle cevaplanabilecek bir soru olduğunu düşünmüyorum.
Ocak'ta Tetrad

1
Oyun nesneleri işaretlemeli. Oyun nesnelerinin birbirleriyle iletişim kurması gerekir. Bu iki şeyin de olması gerekiyor. İlk mesajlaşma ile yapmazsınız çünkü gereksizdir (muhtemelen bir yerdeki tüm nesnelerin bir listesine sahipsiniz, sadece updateonları arayın ). İkincisi çeşitli nedenlerle mesajlaşma ile yapabilirsiniz.
Tetrad

Yanıtlar:


8

Ben buluşun annesi olmanın gereğine inanıyorum. İhtiyacı net ve iyi tanımlanmış olmadığı sürece hiçbir şeyi kodlamayı sevmiyorum. Projenize bir olay mesajlaşma sistemi kurarak başlarsanız, yanlış yaptığınızı düşünüyorum. Sadece altyapınızı oluşturup test ettikten ve projenize tüm parçaları iyi tanımlanmış, çalışan modüllere sahip olduktan sonra, bu modülleri birbirine nasıl bağlayacağınıza odaklanmanız gerektiğine inanıyorum. Her bir modülün şeklini ve gereksinimlerini anlamadan önce bir olay mesajlaşma sistemi tasarlamaya çalışmak bozuk.

Her iki yaklaşımın da avantajları ve dezavantajları nelerdir?

Bazı insanların orada kurulmaya ve kullanılmaya hazır iyi mesajlaşma sistemleri olduğunu iddia edeceğini düşünüyorum. Belki de bu doğrudur. Kesinlikle ihtiyaçlarınıza özel olarak uyarlanmış özel yapım bir çözümün performansı, genel amaçlı bir mesaj veriyolundan daha yüksek olacaktır. Büyük soru şu ki - daha önce inşa edilmiş bir şey kullanmaktan ziyade bir mesajlaşma sistemi oluşturmak için ne kadar zaman harcayacaksınız. Açıkçası, tam olarak ihtiyacınız olan özellik kümesine sahip bir tür olay sistemi bulabilirseniz, bu oldukça kolay bir karardır. Bu yüzden bu kararı vermeden önce tam olarak neye ihtiyacım olduğunu anladığımdan eminim.

Biri diğerinden daha iyi nerede?

Burada hafıza ve kaynaklar hakkında konuşabiliriz. Sınırlı kaynaklara sahip herhangi bir donanım için geliştiriyorsanız, bunu önemli ölçüde kesecek bir olay sistemi kullanmak kesinlikle bir sorundur. Gerçekten de, bence sorun ihtiyacınız olana geliyor, daha önce de belirttiğim gibi, tüm parçaların neye benzediğini görene kadar bilmediğiniz bir şey. Tüm parçaların nasıl görüneceğini önceden bildiğiniz bu sistemleri oluşturmak için yeterli deneyime sahipseniz, bu soruyu da önceden cevaplayabilirsiniz. Sanırım bu deneyime sahip değilsiniz, çünkü eğer bu soruyu sormazdınız.

Etkinlik odaklı oyun tasarımı evrensel ve tüm alanlarda daha mı iyi? Bu nedenle mobil platformlarda bile kullanılması tavsiye edilir mi?

Evrensel ve tüm alanlarda daha iyi mi? Böyle güzel bir battaniye ifadesi kolayca reddedilir. Genel gider ekleyen her şeyin iş yükünden payını taşıması gerekir. Tasarımın yükünü garanti edecek olayları kullanmıyorsanız, yanlış tasarımdır.

Hangisinin daha verimli ve hangisinin geliştirilmesi daha zor?

Verimlilik, nasıl uygulandığına bağlıdır. İyi geliştirilmiş geleneksel bir tasarımın haftanın her günü etkinlik tabanlı bir sistem gerçekleştireceğini düşünüyorum. Bunun nedeni, parçalar arasındaki iletişimin mikro yönetilebilmesi ve süper verimli hale getirilebilmesidir. Tabii ki, bu aynı zamanda onu tamamlamak ve daha verimli hale getirmek için gereken deneyim ve zaman açısından tasarlamayı daha da zorlaştırır. Öte yandan, bu deneyimden yoksunsanız veya uygulamayı iyi geliştirecek zamanınız yoksa, ihtiyaçlarınıza uygun etkinlik tabanlı bir tasarım kullanmak daha verimli olacaktır. Olay tabanlı bir yapıya kolayca sığmayan özel olay gereksinimleriniz varsa, olay tabanlı yapının tasarlanmasını çok zorlaştırabilir - özellikle de tasarımı verimli tutmak için.


Merhaba Eric, sorumla ilgili ayrıntılı görüşünüz için teşekkür ederim. Sizin ve diğerlerinin yanıtlarını okuduğumda, olay mesajlarını uygulamak muhtemelen genel oyun performans artışında bir mucize yaratmaz. Bunun yerine işleri çok karmaşık hale getirecek. Bu soruyu kapatmadan önce biraz daha cevap görmek istiyorum. Kitabın tamamı bu konuyu kapsadığından, dikkate alınması iyi bir fikir gibi görünüyordu. Mesajları kullanma veya kullanmama kararının projenin ortasında verilip verilemeyeceğinden emin değilim. Olay mesajları kullanılıyorsa, genel nesne tasarımı da ayarlanmalıdır.
Bunkai.Satori

Katılmıyorum. Genel nesne tasarımı iyi bir şekilde kapsüllenmişse, her türlü çerçevede kullanılacak kadar esnek olmalıdır. Büyük projelerde iletişim yöntemlerini çok az çalışmayla değiştirebildim çünkü her parça iyi kapsüllenmişti.
Erick Robertson

7

Sanırım burada elma ve portakalları karşılaştırıyorsunuz. Çok biçimliliğin yerini mesajlaşma almaz. Muhtemelen olayların / mesajlaşmanın gevşek bağlı bileşenleri bağlamasını istersiniz. Örneğin. bir çarpışma olduğunda bir varlıktan mesaj göndermek, oyuncu skorunu güncellemek veya belki bir ses efekti tetiklemek için. Böylece bu sınıflar diğer sınıfları tanımıyor ve sadece mesaj gönderiyor ve / veya işliyor.

Ancak oyununuz bir yerde bir güncelleme döngüsüne sahip olacak ve bu güncelleme döngüsüne sahip olduğunuzdan, her karede güncellenmesi gereken tüm oyun varlıklarını güncellemek için kolayca kullanılabilir. Bu mesajlaşmayı kullanmanızı engellemez ...

Oyun varlıklarını eklediğiniz / kaldıracağınız bir tür yapınız varsa , bunları her kareye bir güncelleme mesajı göndermek yerine güncelleme döngünüze dahil edebilirsiniz . Peki , oyununuzun farklı alt sistemlerini bağlamak için mesajlaşmayı kullanırken neden oyun varlıklarınızda güncellemeyi çağırmıyorsunuz? Olay benzeri sistemler için Sinyal / Yuva kavramını da ( qt örneğine bakın ) seviyorum.

Alt satır: Daha iyi bir yaklaşım yok, onlar da özel değil.


Merhaba Bummzack. Sonunda, ilk cevap geldi. Bunun için teşekkür ederim :-) Event Driven Architecture'dan bahsettiğimde, üç anahtar katmana sahip bir MVC sistemi demek istedim: Appliaction, GameView, GameLogic. Bu trhee arasındaki tüm iletişim mesajlaşma yoluyla yapılacaktı. Bu, güncelleme döngüsüne sahip geleneksel sistemden önemli ölçüde farklıdır. Her sistemin farklı mimarisi, bazı avantajları ve dezavantajları vardır ve farklı performans maliyetleri vardır. Bu nedenle, bazı bölgelerde biraz daha iyi olacağına inanıyorum. İyi bir analizden sonra hangisinin daha iyi olduğu sonucuna varabiliriz.
Bunkai.Satori

3
Bunun neden farklı olduğunu anlamıyorum? Bir yerde bir güncelleme döngüsüne ihtiyacınız olacak ve MVC'ye bağlı kalmak istiyorsanız, muhtemelen Denetleyiciyi güncelleyecektir. Daha sonra kontrolör modeli ve görünümü mesajlaştırabilir .. ancak kontrolör genellikle görünümü ve modeli bildiğinden , bunları doğrudan güncelleyebilir. Ancak bu herhangi bir polimorfizmin yerini almaz. Sorunuz ve varsayımlarınız çok teorik geliyor ... belki bazı örnek kodlarla veya referanslarla destekleyebilirsiniz?
bummzack

Yukarıda belirtilen, Oyun Kodlama Tamamlandı kitabı, sanal yöntemlere doğrudan çağrılar üzerinden olay mesajlaşmasını önerir. Mesajlaşma sistemi daha karmaşık görünse de, avantajı, her oyun nesnesinin oyun dünyasını kontrol etmesine gerek olmamasıdır. Oyun dünyası oyun mantığı tarafından sadece bir kez kontrol edilir ve daha sonra sadece durumlarını değiştirmesi gereken nesneler ele alınır. Bu bir farktır ve maliyet tasarrufu anlamına gelebilir. Oyun nesnelerinizin mesajlarla iletişim kuracağına karar verirseniz, her kare olarak adlandırılmazlar - bu nedenle iki yaklaşım birbirini dışlar.
Bunkai.Satori

1
Tetrad'ın orijinal sorunun altındaki yorumlarını yansıtan bir cevaba oy verildi. @ Bunkai.Satori 'Oyun dünyası sadece bir kez kontrol edilir' güncelleme döngüsüdür, güncellenmesi gereken her şey bunu alır. Olay Mesajları nadiren yapılır, ancak yine de motordaki (PlayerDied, MonsterDied, vb.) Bir Update () döngüsünde her kareyi kontrol etmenin bir israf olacağını, ancak bunların büyük olasılıkla Update () döngüsünün kendisi.
James

1
İkinci Sürüme sahipseniz, Ana Döngüyü Kontrol Etme bölümüne bakın. 3. baskıda aynı şekilde adlandırılmalıdır. Bu gerçekten sorunuzu cevaplamalıdır.
Ray Dey

4

Bu, bummzack'in cevabına bir yorum olarak başladı, ancak uzun sürdü.

Aslında eşzamansız yapmadığınız sürece (yeni bir iş parçacığında olaylar gönderir), nesneleriniz yine de notu eşzamanlı olarak alır. Olay dağıtıcınızın, hücrede bağlantılı bir listeyle temel bir karma tablo kullandığını varsayarsak, sıra, nesnelerin o hücreye eklenme sırası olacaktır.

Ayrıca, herhangi bir nedenden dolayı işlev işaretçileri kullanmaya karar vermedikçe, ileti alan her nesne IEventListener'ı (veya her ne çağırırsanız) uygulamalı olduğundan, sanal işlev çağrılarını kullanmaya devam edersiniz. Olaylar, polimorfizm kullanarak oluşturduğunuz yüksek düzeyli bir soyutlamadır.

Oyundaki farklı sistemleri senkronize etmek veya çeşitli nesnelerin ve sistemlerin tepkilerinin söz konusu olayların açıkça tanımlanamaması veya istediğiniz şekilde senkronize edilmesi için çeşitli oyun içi olaylar için bir çamaşır yıkama yöntemi listesini çağırmak zorunda kaldığınız olayları kullanın. gelecekte söz konusu olaylara daha fazla tepki eklemek.

Onlar harika bir araç, ancak bummzack'in dediği gibi, polimorfizm ve olayların aynı sorunu çözdüğünü varsaymayın.


Merhaba Bearcdp, Cevabınız için teşekkürler. Bana mantıklı geliyor. Aklımda olay mesajlarına oy veren bir şey var: diyelim ki sahnede 200 nesne var. Tüm nesnelerde kare başına işlev çağrıları kullanırsanız, her karede çarpışma için 200 nesnenin tümünü kontrol etmeniz gerekir (örnek; tabii ki çağrı aralıkları yönetilebilir.) Olay mesajlaşma ile oyun dünyası yalnızca bir kez incelenir. 5 çarpışma varsa, kare başına aramalarla 200 çarpışma algılama testi yerine çarpışma olayıyla ilgili mesajlarla yalnızca 5 nesne bildirilir. Senin görüşün nedir?
Bunkai.Satori

2
gameworld incelemek ?? Bu ne anlama geliyor? İleti göndermek için ihtiyaç duyduğu 5'i izole etmek için aynı 200 denetimi çalıştırmak anlamına gelecektir. Sanal işlev kavramı ile, gameworld sadece bir kez kontrol edilir (sırayla her nesnenin işlevi) ve daha sonra sadece mesajlaşma sisteminin yükü olmadan durum değişiklikleri gerektiren 5'e geçer.
Steve H

1
Steve H'yi dinleyin, dünya kendi kendine çarpışmaz. Öncelikle PlayerJump, EnemyHit gibi üst düzey olaylar için etkinlikler kullanıyorum. Çarpışma kontrolünün verimliliğini ele almak için, oyununuzdaki nesnelerin fiziksel konumunu düzenlemek için bir veri yapısı seçmeniz gerekir, böylece hangi nesnelerin çarpışma için kontrol edilmesi ve gerekmemesi gerektiğini önceliklendirebilirsiniz. Çarpışan tüm nesne çiftlerini belirledikten sonra, ilgili çarpışma verileriyle (iki nesne, hız / konum / normal veriler vb.) Bir olay gönderebilirsiniz.
michael.bartnett

Merhaba Steve ve Beardcp, yorumlarınız için teşekkürler. Yazdıklarınız mantıklı. Olay mesajlaşma sisteminin birçok olası uygulaması olabileceği anlaşılıyor. Yukarıda belirtilen kitabın da söylediği gibi, çerçeve başına sanal işlev kavramının tamamen değiştirilmesi söz konusu olabilir. Bununla birlikte, mesajlaşma sistemi, dediğiniz gibi, çerçeve başına sanal işlev konseptiyle birlikte bulunabilir.
Bunkai.Satori

İşlev işaretçileriyle ilgili olarak neden "nedense" diyorsunuz? Bir olay sistemini sıfırdan yazdığım zamanlarda neredeyse bu şekilde uyguladım (birinci sınıf işlevlere sahip dillerde çalışıyorum ama aynı fikir; işlevi olay hub nesnesine aktarın ve bu nesne dinleyici işlevlerini eşler Bu yaklaşımın bir dezavantajı olup olmadığını merak ediyorum.
12'de

2

Birini ya da diğerini seçmenin oldukça yanlış olduğunu söyleyebilirim. Bazı nesnelerin her kareyi çağırması gerekir, bazıları gerekmez. Oluşturmak istediğiniz bir nesneniz varsa, her karede bir render araması yapmanız gerekir . Olaylar bu değişikliği yapamaz. Aynı şey objelerden herhangi zamana dayalı fiziği için de geçerlidir gerekir her çerçeve diyoruz.

Ancak, nesne yönetimi nesnelerime veya kullanıcı girdi nesnelerime veya bunun gibi herhangi bir şeye her kareyi aramıyorum. Çerçevedeki her nesneye toplu sanal çağrılar korkunç bir fikirdir.

Herhangi bir nesne için kullanılan tasarım bu nesneler ihtiyaçlarına göre ve gerektiği değil, bir bütün olarak sistemin bir ideolojiye göre.

İlk cümlemde daha açık olacak şekilde düzenlendi.


Merhaba DeadMG, açıklayayım: Yukarıda belirtilen durumda, tasarım üç ana bölüme ayrılmıştır: Aplike katmanı (donanım erişimi), Game Logic, Game View. Çerçeve bazında görüntülenen şey Oyun Görünümüdür. Ancak, Game View bir kullanıcı girişi kaydettiğinde (örn. Oyunu kovalarken fren pedalı basılı) işlem için Game Logic'e "Car 2 Brake Pressed" mesajı gönderir. Game Logic bu eylemi değerlendirir, otomobilin davranışını hesaplar ve Game View'a mesaj gönderir: "Car 2 Block Tires", "Car 2 Move X, Y". Bu şekilde, her araçta frene basılmışsa, çerçeve başına kontrol edilmesi gerekmez.
Bunkai.Satori

@Bunkai: Yani olay odaklı bazı tasarımlarınız ve her kare olarak adlandırılan bazı tasarımlarınız var. Bu benim cevabımla aynı fikirde.
DeadMG

Sizinle anlayış bulduğum için mutluyum, bu soru bugün burada biraz tartışmalı olduğu için :-)
Bunkai.Satori
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.