Bir Oyun Motorunda Etkinlikle İlgili İletişim: Evet mi Hayır mı?


62

Game Coding Complete'i okuyorum ve yazar, oyun nesneleri ve modülleri arasında Event Driven iletişimini önermektedir .

Temel olarak, tüm canlı oyun aktörleri, dahili bir olay mesajlaşma sistemi aracılığıyla ana modüller (Fizik, AI, Oyun Mantığı, Oyun Görünümü vb.) İle iletişim kurmalıdır. Bu, etkin bir etkinlik yöneticisi tasarlamak zorunda kalması anlamına gelir. Kötü tasarlanmış bir sistem, özellikle mobil platformları etkileyen CPU döngülerini yiyor.

Bu kanıtlanmış ve önerilen bir yaklaşım mı? Kullanıp kullanmamaya nasıl karar vermeliyim?


Merhaba James, cevabın için teşekkür ederim. Her ne kadar kitap Event Driven iletişimini çok fazla CPU kaynağı tüketen çok karmaşık bir sistem olarak tanımlasa da hoşuma gidiyor.
Bunkai.Satori

Bir cevaba koyun ve yığın taşması üzerine bir cevap olarak verdiğim bir olay mesajlaşma sisteminin üst düzey genel bakışına bir link ekleyin. Keyfini çıkarın! Sadece bazı insanların karmaşık olarak düşündüklerinin böyle olması gerekmediğini unutmayın :)
James

Bu cevabı c ++ 11 ile yapılmış olduğu gibi kontrol edebilirsiniz: stackoverflow.com/a/22703242/2929762
user2826084

libuvson zamanlarda başarılı bir etkinlik kütüphanesi olarak ortaya çıkmıştır. (C. Node.js en meşhur kullanım davasıdır.)
Anko

Yanıtlar:


46

Bu bir genişleme benim yorumum önerildiği gibi, tam bir cevaba.

Evet , sade ve basit. İletişimin olması gerekiyor ve “Henüz orada mıyız?” Durumları varken. -tip türü yoklama gerekir, genellikle başka bir şey yapmaları gerekip gerekmediğini kontrol etmek için zaman harcarlar. Bunun yerine, yapmaları söylenen şeylere tepki vermelerini sağlayabilirsiniz. Ayrıca, nesneler / sistemler / modüller arasında iyi tanımlanmış bir iletişim yolu, paralel kurulumları önemli ölçüde artırır.

Yığın Taşması ile ilgili bir olay mesajlaşma sistemine üst düzey bir genel bakış verdim . Okuldan profesyonel oyun başlıklarına ve şimdi de her zaman kullanıma uygun hale getirilmiş oyun dışı ürünler olarak kullandım.

EDIT : Hangi nesnelerin mesajı alması gerektiğini nasıl bildiğiniz konusunda bir yorum sorusunu ele almak için : Nesnelerin kendilerine Requestolaylar hakkında bilgilendirilmeleri gerekir . Sizin EventMessagingSystem(EMS) Register(int iEventId, IEventMessagingSystem * pOjbect, (EMSCallback)fpMethodToUseForACallback)eşleştirmenin yanı sıra Unregister( iEventIdnesne işaretçisi ve geri arama dışında bir öğe için benzersiz bir giriş yaparak ) gerekir. Bu şekilde, bir nesne bir mesaj hakkında bilmek istediğinde Register(), sistemde olabilir. Artık olaylar hakkında bilgi sahibi olması gerekmediğinde,Unregister(). Açıkçası, bu geri arama kayıt nesnelerinin bir havuzunu ve bunları listelerden eklemek / çıkarmak için etkili bir yol istersiniz. (Genelde kendi kendini sıralayan dizileri kullandım; kullanılmayan nesnelerin bir havuz yığını ile gerektiğinde boyutlarını değiştiren diziler arasında kendi tahsisatlarını takip ettiklerini söylemenin süslü bir yolu).

EDIT : Bir güncelleme döngüsü ve bir olay mesajlaşma sistemi ile tamamen çalışan bir oyun için, eski bir okul projemi incelemek isteyebilirsiniz . Yukarıda bağlantılı Yığın Taşması direği de buna karşılık gelir.


Merhaba James, dahili olay mesajlaşma sistemini daha fazla düşündüğüm için, motora daha fazla maliyet eklemek zorunda olmadığını düşünüyorum. Örneğin, ekranda 50 nesne varsa, ancak yalnızca 5 tanesinin davranışlarını değiştirmesi beklenir; geleneksel sistemde, 50 obbistin, bir şeyler yapıp yapmamaları gerektiğini görmek için tüm olası eylemlerini kontrol etmesi gerekir. Bununla birlikte, olay mesajlaşma kullanımıyla, belirli eylem değişikliği olan bu 5 projeye yalnızca 5 mesaj gönderilecektir. Bu zaman kazandıran bir yaklaşım gibi görünüyor.
Bunkai.Satori

Yukarıdaki cevabımdaki sisteme bağlı çalışma, nesnelerin yalnızca istedikleri mesajları duymak için kayıt olmalarıdır. Bunu bir avantaj olarak 100-200 nesnenin olabileceği video oyunlarında kullanacağız. oyuncunun doğrudan etkileşime girebileceğini “aktive et”, 10 ya da öylesine dinleyen şeylerin sayısını koruyarak. Sonuçta bu tür bir sistemde “daha ​​var mıyız?” Den daha akıllı olmalı. Yoklama sistemi ve iletişim açısından, en azından bir motorun ek yükünü azaltmalıdır.
James

Beni şaşırtan olay odaklı sistemle ilgili bir şey var: Geleneksel sistem altında, her nesnenin önceden tanımlanmış bir dizi metodu (OnUpdate (), OnMove (), OnAI (), OnCollisionCheck () ...) düzenli olarak adlandırıldığı geleneksel sistem altında, her nesne durumunu kontrol etmek ve yönetmek için sorumludur. Olayla çalışan sistemde, her nesnenin bazı ana sistem denetleme koşulu olmalı ve ardından bazı olayın tespit edildiği kişilere mesaj gönderilmelidir. Bana göre bu, olası nesne durumlarını standartlaştırıyor ve benzersiz nesne davranışı yaratma özgürlüğünü sınırlandırıyor. Bu doğru mu?
Bunkai.Satori

Gözlemci desen yoklama için tipik bir alternatiftir. en.wikipedia.org/wiki/Observer_pattern
Ricket

1
@ hamlin11 Bu bilgilerin hala insanlara yardım etmesine sevindim :) Kayıt ile ilgili olarak, eğer bu biraz olursa, hız için optimize etmek isteyeceğiniz, kayıt nesnelerinden bir havuza sahip olacağınızı vb. unutmayın
James

22

Bence oyununuzu yapmaya başlamalı ve rahatladığınız şeyi uygulamalısınız. Bunu yaptığınız gibi kendinizi MVC'yi bir yerlerde kullanarak bulacaksınız, başkalarını değil; bazı yerlerde olaylar olur, diğerlerinde değil; bazı yerleri birleştirir, ancak diğerlerini miras alır; bazı yerlerde temiz tasarım, bazılarında tasarım özgürce.

Ve bu sorun değil, çünkü işiniz bittiğinde aslında bir oyuna sahip olacaksınız ve oyun mesaj gönderme sisteminden çok daha iyi.


2
Merhaba Joe, cevabın için teşekkürler, hoşuma gitti. Herhangi bir yaklaşımı yapay olarak itmeye gerek olmadığına inanıyorsunuz. Uygulamaları çalışacağımı düşündüğüm gibi tasarlamalıyım ve eğer daha sonra işe yaramazsa, basitçe tekrarlayacağım.
Bunkai.Satori

Bu yüzden sistem var. Pek çok insan tam olarak söylediklerini yaptın, kabusa şahit oldular ve daha iyi bir yol olması gerektiğini söyledi. Ya kendi hatalarını tekrarlayabilir ya da onlardan bir şeyler öğrenebilir ve belki daha fazla ilerleyebilirsin.
user441521,

16

Daha iyi bir soru, hangi alternatifler var? Fizik, AI vb. İçin uygun şekilde bölünmüş modüllere sahip böyle karmaşık bir sistemde, bu sistemleri başka nasıl düzenleyebilirsiniz?

Mesaj iletme bu sorunun en iyi çözümü gibi görünüyor. Şu anda alternatifleri düşünemiyorum. Ancak pratikte iletilen birçok mesaj örneği var. Aslında, işletim sistemleri işlevlerinden bazıları için mesaj iletmeyi kullanır. Gönderen Vikipedi :

Mesajlar ayrıca süreçler arası iletişim aracı olarak aynı anlamda kullanılır; diğer yaygın teknik, verinin bunun yerine temel veri öğeleri dizisi olarak gönderildiği akışlar veya borulardır (sanal devrenin üst düzey sürümü).

(İşlemler arası iletişim, işletim sistemi ortamında işlemler arasındaki (yani programların çalışan örneklerini) arasındaki iletişimdir)

Yani bir işletim sistemi için yeterince iyiyse, muhtemelen bir oyun için yeterince iyidir, değil mi? Başka faydaları da var, ancak Wikipedia'dan geçen ve geçen mesajla ilgili makalenin açıklama yapmasına izin vereceğim .

Ayrıca Stack Overflow, "Bir programdan geçen mesaj için veri yapıları?" , okumak isteyebilirsiniz.


Merhaba Ricket, cevabınız için teşekkürler. Oyun nesnelerinin birbirleriyle iletişim kurmasına izin vermek için başka hangi yolların kullanılabileceğini sordunuz. Aklıma gelen, doğrudan yöntem çağrılarıdır. Size çok fazla esneklik sağlamaz, ancak diğer yandan olay mesajı oluşturma, iletme, okuma, vb. Engeller. Doğru, mobil platformlar hakkında konuşuruz, ileri seviye oyunlar hakkında değil. İşletim sistemi, iç mesajlaşma sistemini büyük ölçüde kullanıyor. Ancak, küçük gecikmelerin bile aksamalara neden olduğu gerçek zamanlı olarak çalışmak üzere tasarlanmamıştır.
Bunkai.Satori

Bu soruyu bir süre açık tutayım. Kapatmadan önce daha fazla görüş almak istiyorum.
Bunkai.Satori

Doğrudan yöntem çağrıları genellikle birbirini arayan sınıfların eşleşmesiyle sonuçlanır. Bu, değiştirilebilir olması gereken bileşenlere ayrılmış bir sistem için iyi değildir. Doğrudan yöntem çağrılarını daha az uyum içinde kolaylaştırabilen bazı modeller vardır (örneğin, MVC'nin "denetleyici" kısmı, temelde bu soruyu, siz birleştirmeden modelin sorgularını kolaylaştırmak için kullanır), ancak genel olarak mesaj iletmenin tek yoludur. alt sistemler arasında sıfır bağlantıya sahip bir sistem (veya en azından bildiğim tek yol).
Ricket

Ah, şimdi kalıpları tartışmaya başladık. Bu programlama yaklaşımı hakkında biraz duydum. Şimdi, kalıpların ne olduğunu anlamaya başladım. Uygulama tasarımına tamamen farklı bir bakış açısı var. Her nesneyi kontrol etmek için aynı kodu kullanırken nesneleri kontrol edebilirsiniz. Nesneyi kontrol ettikten sonra özelliklerini uygun şekilde ayarlayın.
Bunkai.Satori

1
"Veri Yapıları ..." sorusu ŞAŞIRTICI bir cevaba sahiptir. Seçtiğiniz cevap ve beraberindeki Nebula3 makalesi, gördüğüm boyuttaki oyun motoru mimarisinin en iyi açıklaması.
deft_code

15

Mesajlar genellikle şu durumlarda iyi çalışır:

  1. Mesajı gönderen şey alınsa bile aldırmaz.
  2. Gönderenin, alıcıdan anında yanıt alması gerekmez.
  3. Tek bir göndereni dinleyen birden fazla alıcı olabilir.
  4. Mesajlar nadiren veya öngörülemeyen olarak gönderilir. (Başka bir deyişle, her nesnenin her karede bir "güncelleme" mesajı alması gerekiyorsa, mesajlar sizi pek satın almaz.)

İhtiyaçlarınız o liste ile eşleştikçe, uygun iletilerin daha iyi olması gerekir. Çok genel düzeyde, oldukça iyiler. Yoklama ya da diğer küresel çözümlerin aksine hiçbir şey yapmamak için CPU döngülerini boşa harcamamak için iyi bir iş çıkardılar. Onlar her zaman yardımcı olan bir kod temeli parçalarını ayırma konusunda harika.


4

James ve Ricket'ten bugüne gelen harika cevaplar, sadece dikkat notu eklemek için cevap veriyorum. İleti iletme / olaya dayalı iletişim, geliştiricinin cephaneliğinde kesinlikle önemli bir araçtır, ancak kolayca aşırı kullanılabilir. Bir çekiçiniz olduğunda, her şey bir çiviye benziyor, vb.

Kesinlikle,% 100, başlığınızın etrafındaki verilerin akışını düşünüyor olmalı ve bilgilerin bir alt sistemden diğerine nasıl geçtiğinin tam olarak farkında olmalısınız. Bazı durumlarda mesaj atma en iyisidir; diğerlerinde, bir alt sistemin paylaşılan nesneler listesi üzerinde çalışması, diğer alt sistemlerin de aynı paylaşılan listede çalışmasına izin verilmesi daha uygun olabilir; ve bunun yanında birçok yöntem.

Her zaman, hangi alt sistemlerin hangi verilere erişmesi gerektiğini ve ne zaman erişmeleri gerektiğinin farkında olmalısınız. Bu, paralelleştirme ve optimize etme yeteneğinizi etkilemenin yanı sıra, motorunuzun farklı parçaları çok fazla dolandığında daha sinsi sorunları önlemenize yardımcı olur. Verilerin gereksiz yere kopyalanmasını en aza indirmeyi ve veri düzeninizin önbellek kullanımınızı nasıl etkilediğini düşünmeniz gerekir. Hepsi, her durumda en iyi çözüme yönlendirecektir.

Olduğu gibi, üzerinde çalıştığım her oyunun hemen hemen hiç senkronize olmayan mesajlaşma / olay bildirim sistemi vardı. Karmaşık ve hızla değişen tasarım ihtiyaçları karşısında bile, kısa ve özlü, verimli bir bakım kodu yazmanıza olanak tanır.


İyi ek bilgi için +1. Merhaba MrCranky, Teşekkürler. Söylediklerinize göre, mobil oyunlar için bile Event Messaging sistemini göz önüne almanız iyi olur. Ancak, planlama göz ardı edilmemeli ve mesajlaşma sisteminin nerede kullanılacağı çok iyi düşünülmelidir.
Bunkai.Satori

4

Eh, bu yazının oldukça eski olduğunu biliyorum ama dayanamadım.

Geçenlerde bir oyun motoru yaptım. Render ve fizik için 3 boyutlu parti kütüphaneleri kullanıyor, fakat varlıkları ve oyun mantığını tanımlayan ve işleyen temel kısmı yazdım.

Motor kesinlikle geleneksel bir yaklaşım izler. Tüm varlıklar için güncelleme işlevini çağıran ana güncelleme döngüsü vardır. Çarpışmalar, doğrudan varlıklar üzerindeki geri aramalarla rapor edilir. Varlıklar arasındaki iletişim, varlıklar arasında değiştirilen akıllı işaretçiler kullanılarak yapılır.

İlkel bir mesaj sistemi vardır, motor mesajlarına yalnızca küçük bir varlık grubunu işler. Bu mesajların bir oyun etkileşiminin sonunda (örneğin bir varlık yaratma veya yok etme) işlenmesi tercih edilir çünkü güncelleme listesine karışabilirler. Böylece, her oyun döngüsünün sonunda küçük bir mesaj listesi tüketilir.

İlkel mesaj sistemine rağmen, sistemin büyük ölçüde "güncelleme döngüsü tabanlı" olduğunu söyleyebilirim.

İyi. Bu sistemi kullandıktan sonra çok basit, hızlı ve iyi organize olduğunu düşünüyorum. Oyun mantığı görünürdür ve varlıkların içinde bulunur, bir mesaj quewe gibi dinamik değildir. Olayı yönlendirmek istemezdim çünkü bence olay sistemleri oyun mantığına gereksiz bir karmaşıklık kazandırıyor ve oyun kodunun anlaşılmasını ve hata ayıklamasını çok zorlaştırıyor.

Ancak, benim gibi saf bir "güncelleme döngüsü tabanlı" sistemin de bazı sorunları olduğunu düşünüyorum.

Örneğin, bazı anlarda bir varlık "hiçbir şey yapma" da olabilir, oyuncunun yaklaşmasını ya da başka bir şeyi bekliyor olabilir. Bu durumların çoğunda, işletme hiçbir işlem yapmadan işlemci zamanını yakar ve varlığı kapatmak ve belirli bir olay gerçekleştiğinde açmak daha iyidir.

Bu yüzden, bir sonraki oyun motorumda farklı bir yaklaşım benimseyeceğim. İşletmeler güncelleme, çizim, çarpışma algılama vb. Motor işlemleri için kendilerini kaydedeceklerdir. Bu olayların her biri, gerçek varlıklar için ayrılmış varlık arayüzleri listelerine sahip olacaktır.


Varlıkların, oyundaki her türlü karmaşıklıkla yönetilmesi zor olan canavar kodu üsleri haline geldiğini göreceksiniz. Onları bir araya getirmeye başlayacaksınız ve özellik eklemek veya değiştirmek için emmek zorunda kalacaksınız. Özelliklerinizi küçük bileşenlere bölerek özellikleri korumak ve eklemek daha kolay olacaktır. Öyleyse soru, bu bileşenlerin nasıl iletişim kurdukları olur? Cevap, argümanlardaki ilkel verileri iletirken, bir bileşenin bir başkasının fonksiyonlarını yükselten olaylardır.
user441521,

3

Evet. Oyun sistemlerinin birbirleriyle iletişim kurması çok etkili bir yoldur. Olaylar, birçok sistemi birleştirmenize yardımcı olur ve hatta birbirlerinin varlığını bilmeden, işleri ayrı ayrı derlemenizi mümkün kılar. Bu, sınıflarınızın daha kolay prototip edilebildiği ve derleme sürelerinin daha hızlı olduğu anlamına gelir. Daha da önemlisi, bağımlılık karışıklığı yerine düz bir kod tasarımı ile bitirdiniz.

Olayların bir diğer büyük yararı, kolayca bir ağ üzerinden veya başka bir metin kanalı üzerinden yayınlanmasıdır. Daha sonra oynatmak için bunları kaydedebilirsiniz. İmkanlar sonsuzdur.

Başka bir avantaj: Aynı olayı dinleyen birkaç alt sisteminiz olabilir. Örneğin, tüm uzak görünümleriniz (oyuncular) taraf oluşturma etkinliğine otomatik olarak katılabilir ve sizin tarafınızdan çok az çalışma yaparak her müşterideki varlıkları yaratır. Olayları kullanmasaydınız, ne kadar iş olacağını düşünün: bir yere Update()arama yapmak veya view->CreateEntityOyun mantığından (görüşle ilgili bilginin ve hangi bilgiye ihtiyaç duymadığı) ait olmak zorundasınız . Olayları olmadan bu sorunu çözmek zor.

Olaylarla, yalnızca olaylara abone olan ve oyununuzda bir şey olduğunda onların işini yapabilen sınırsız çeşitlilikteki sonsuz sayıda nesneyi destekleyen zarif ve ayrık bir çözüm elde edersiniz. Bu yüzden olaylar harika.

Daha fazla detay ve burada bir uygulama .


Tek taraflı olsa da harika noktalar. Her zaman genellikten şüpheliyim: Olaylar için kullanım karşıtı davalar var mı?
Anko

1
Kullanım karşıtı noktalar: Kesinlikle doğrudan yanıt almanız gerektiğinde. Bazı olaylarda ne yapmak istersen, her zaman doğrudan ve aynı iş parçacığında yürütülür. Dışarıda hiçbir gecikme olmadığında çağrıları tamamlamayı geciktirebilecek bir gecikme olabilir. Sadece doğrusal bağımlılıklarınız olduğunda. Nadiren aynı anda birden fazla şey yaptığınızda. Node.js dosyasına bakarsanız, tüm io çağrıları olay tabanlıdır. Node.js, olayların% 100 doğru uygulandığı bir yerdir.
user2826084

Olay sisteminin zaman uyumsuz olması gerekmez. Gerektiğinde eşitleme yaparken eşzamansı taklit etmek için coroutinler kullanabilirsiniz.
user441521,

2

Gördüğüm kadarıyla, tamamen mesajlaşmaya dayalı bir motora sahip olmak pek yaygın görünmüyor. Tabii ki, ağ oluşturma, GUI ve muhtemelen diğerleri gibi, böyle bir mesajlaşma sistemine kendilerini iyi borç veren alt sistemler var. Genel olarak, düşünebildiğim birkaç sorun var:

  • Oyun motorları büyük miktarda veri ile uğraşır.
  • Oyunlar hızlı olmalı (20-30 FPS minimum olmalıdır).
  • Genellikle bir şeyin yapılıp yapılmadığını veya ne zaman yapılacağını bilmek gerekir.

“Oyun mümkün olduğunca verimli olmalı” ortak oyun geliştiricisi yaklaşımıyla, böyle bir mesajlaşma sistemi bu kadar yaygın değildir.

Ancak, devam edip denemeniz gerektiğine katılıyorum. Böyle bir sistemde kesinlikle pek çok avantaj var ve bilgisayar gücü bugün ucuza temin edilebilir.


Buna katılıyor muyum bilmiyorum. Alternatif, savurgan olan oylamadır. Sadece olaylara cevap vermek en verimli olanıdır. Evet, gerçekleşecek ve olayları arttıracak bir oylama olacak, ancak olaya yönelik çok sayıda şey var.
user441521

Ben de buna katılmıyorum. Olay mesajlaşma alt sistem-alt sistem iletişimi için tasarlandığından, oyun motorlarının uğraştığı veri miktarı büyük oranda önemsizdir. Oyun nesneleri, diğer oyun nesneleriyle doğrudan iletişim kurmamalıdır (nesnelerdeki özel olay işleyicileri bir istisna olabilir). Bu nispeten az sayıda alt sistem ve onların "ilgi" alanlarından dolayı, iyi tasarlanmış bir mesajlaşma omurgasının çok dişli bir motordaki performans maliyeti önemsizdir.
Ian Young,
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.