Etkinlik sistemi kurmanın daha iyi bir yolu var mı?


9

Etkinlik Sistemleri şaşırtıcıdır, son derece hantal bir kod uydururlar ve nesnelerin ve oyun döngüsünün kolay iletişimi yoluyla oyunların dinamik olarak oluşturulmasına gerçekten izin verirler. Mevcut uygulamamın verimliliği ile zor anlar yaşıyorum. Şu anda, nesne listelerini yanıtladıkları olaylara ayırma konusundaki küçük optimizasyonum harikalar yaptı, ancak yapabileceğim daha çok şey olmalı.

Şu anda iki yöntemim var:

  1. En basit: bir olay gönderildiğinde tüm nesneler bir vektöre eklenir Tüm nesneler olayı handle_event () yöntemiyle gönderir

  2. Daha karmaşık: Ben anahtar ve int değeri olarak int ile bir harita var. Bir olay türü eklendiğinde, bu haritaya int eklenir (daha iyi bir yol olmalı)
    , daha sonra nesnelerin vektörleri vektörü bu tür olayı işlemek için yeni bir vektörü geri iter.
    Bir olay çağrıldığında, eventTypes eşlemesindeki ilgili int'i yalnızca nesne vektörlerinin vektörü içindeki türe çağırır ve o olayı, o olay türünü işleyen her nesneye gönderir.

Bu ilk yöntem, çok sayıda nesne için oldukça yavaş (açıkçası), ancak çok az sayıda nesne için oldukça hızlıdır. İkinci yöntem, farklı olay türlerini işlemek isteyen büyük nesnelerle oldukça hızlıdır, ancak aynı tür olayı işleyen nesnelerle nesne başına ilk yöntemden daha yavaştır.

Daha hızlı (çalışma süresi açısından) bir yol var mı? Dize türünden bir int aramanın daha hızlı bir yolu var mı? (Başlangıçta bir enum vardı, ancak istenen dinamizm seviyesi nedeniyle gerekli olan özel türlere izin vermedi.)


1
Bu, Hash Haritalarının (veya Hash Tablosunun) ne için olduğu, dize daha sonra doğrudan bir diziye bakmak için kullanılan bir karma numarasına kadar hesaplanır. en.wikipedia.org/wiki/Hash_table
Patrick Hughes

İyi bir soru: bu gerçekten bir performans darboğazı mı yoksa sadece erken endişeleniyor musunuz?
Jari Komppa

Zaten uygulanmış ve birçok nesne kullanıldığında bir darboğaz var. Darboğaz eksikliği hakkındaki önceki yorumum uygulamanın kendisinde değil, aslında aynı sayıda nesnenin gerçekte ele alındığı yukarıdaki iki uygulama arasındaki hız farkıydı. Olay sistemleri oluşturmanın diğer yöntemlerini umuyordum ... Ancak bu konudaki bazı fikirler, özellikle olay sisteminin yüklenmesinde (100.000 nesnelerle 11-25 tam saniye yükleme süresi) hızı biraz artıracak
ultifinitus

100K nesneleri sadece bir oyun için korkunç yüksek geliyor. Bu bir sunucu mu yoksa son kullanıcı istemci uygulaması mı?
Patrick Hughes

Bu benim motorum, bu yüzden gerçekten esneklik için gidiyorum. Sunucu uygulamalarında ve son kullanıcı uygulamalarında kullanılacaktır (daha az sıklıkla ilk, optimizasyon)
ultifinitus

Yanıtlar:


5

Büyük performans darboğazının dize adlarından olay kimliklerini (tamsayılar) aradığını söylüyorsunuz. Oyunu çalıştırmadan önce veya muhtemelen seviye yüklenirken tüm olay adlarını tamsayılara dönüştürmek için oyun verilerinizi önceden işleyebilirsiniz; oyun sırasında herhangi bir dönüşüm yapmak zorunda kalmazsınız.

Nesneler sık ​​sık oluşturuluyor ve yok ediliyorsa, nesnelerin vektörlerinde çok fazla dalgalanma olabilir. Bu durumda, vektörler yerine bağlantılı listeler kullanarak faydalanabilirsiniz; ekleme ve silme için daha hızlıdır.


Darboğaz büyük değil (100.000 nesne için .0000076 ms / nesne kaybeder) ama fikrinizin harika bir fikir olduğunu düşünüyorum! Ben aslında kimliği bir kez arama yapacağız ve eventID orijinal dize veri yerine int olarak depolanmış olacağını düşünüyorum. Ve aslında bağlantılı listeleri düşünmemiştim, iyi fikir.
19:19

1
+1 Kimliklerin önişlenmesi için. Ayrıca, her modülün benzer bir şeyle elde edebileceği bir EventType türüne sahip olarak tembel olarak da yapabilirsiniz EventType takeDamageEvent = EventSystem::CacheEventType("takeDamageEvent");. Sınıfların statik bir üyesi olun ve ona ihtiyaç duyan her sınıfta yalnızca bir tane kayan var.
michael.bartnett

2
Dizeleri yerine kimlikleri depolamanın hata ayıklamayı biraz zorlaştıracağını unutmayın. Bir nesnenin nereden geldiğini belirten bazı metinleri görmek her zaman yararlıdır. Hata ayıklama amacıyla sakladığınız kimliği ve dizeyi saklayarak yarı yoldan gidebilirsiniz (belki de sürüm derlemelerinde kaldırılır).
Nicol Bolas

2

Önce basit şeyleri yoldan çıkaralım. Bu map, dizeler (muhtemelen olayın adı) ve tamsayılar (kayıtlı olay dinleyicilerinin dizini) arasındadır.

A'daki arama süresi mapiki şeye dayanır: haritadaki öğe sayısı ve iki anahtar arasındaki karşılaştırmanın yapılması için gereken süre (önbellek sorunlarını yok saymak). Arama süresi bir sorunsa, işlemenin bir yolu dize türünü değiştirerek karşılaştırma işlevini değiştirmektir.

Diyelim ki std::stringve operator<karşılaştırma için kullandınız . Bu oldukça verimsizdir; byte-wise karşılaştırması yapar. Gerçek dizgiyi karşılaştırmadan daha az umursamazsınız; sadece zayıf ve zayıf bir sipariş veren bir tür karşılaştırmaya ihtiyacınız var (çünkü mapaksi halde çalışmıyor).

Yani bunun yerine 32 baytlık sabit uzunluklu bir dize kullanmalısınız std::string. Bunları tanımlayıcılar için kullanıyorum. Bu sabit dizeler için karşılaştırma testleri bayt-bazlı karşılaştırmalar yapmaz; bunun yerine 32 bit (veya 64 bit) karşılaştırmaları yaparlar. Her 4 baytı imzasız bir tam sayı olarak alır ve diğer dizenin karşılık gelen 4 baytıyla karşılaştırır. Bu şekilde karşılaştırma en fazla 8 karşılaştırma yapar. Siparişin verilerle karakter olarak bir ilgisi olmamasına rağmen, katı ve zayıf bir sipariş sağlar.

31 bayt daha uzun dizeleri (NULL karakter gerekir) saklamak dize keser (ama uçları yerine, ortadan. Ben entropi başında ve sonunda en büyük eğilimindedir bulmak). Ve bundan daha kısa olan dizeler kalan karakterleri doldurur \0.

Şimdi, maptamamen hendek ve bir karma tablo kullanabilirsiniz. Gerçekten 100.000'den fazla farklı türde etkinlik varsa, bu iyi bir fikir olabilir. Ama bunun uzaktan makul bir şey olacağı bir oyun bilmiyorum.


Bu nedenle std :: string yerine 32 baytlık sabit uzunluklu bir dize kullanmalısınız. Fantastik! Dize türünü değiştirmeyi düşünmemiştim.
ultifinitus

0

Genel soruyu cevaplamak için:

Etkinlik Sistemi Kurmanın Daha İyi Yolu

Hiç yok. Yapabileceğiniz tek şey, etkinlik sistemleriniz için özel ihtiyaçlarınızı belirlemek (birkaç farklı olabilir) ve daha sonra doğru iş için doğru aracı kullanmaktır.

Tonlarca olay sistemini uygulamaya koydum ve genelleştirmeye çalıştım ve bu sonuca vardım. Çünkü derleme zamanı veya çalışma zamanı yaparsanız, nesne hiyerarşileri veya yazı tahtaları vb. Kullanırsanız tradoff'lar gerçekten farklıdır.

En iyi yol, farklı olay sistemlerini incelemek ve sonra hangisinin hangi durumda kullanılacağına dair ipuçlarına sahip olmaktır.

Şimdi, en esnek sistemi istiyorsanız, olayların dinamik özelliklerine sahip bir kara tahta sistemi (çalışma zamanı) uygulayın ve çok esnek ama belki de çok yavaş bir şeye sahip olacaksınız.

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.