Bu bileşen mimarisiyle doğru yolda mıyım?


9

Son zamanlarda, derin sınıf hiyerarşilerinden kurtulmak ve bunları yapılandırılabilir bileşenlerle değiştirmek için oyun mimarimi yenilemeye karar verdim. Değiştirdiğim ilk hiyerarşi, Öğe hiyerarşisidir ve doğru yolda olup olmadığımı bilmek için bazı tavsiyeler istiyorum.

Daha önce, böyle bir şey gitti bir hiyerarşi vardı:

Item -> Equipment -> Weapon
                  -> Armor
                  -> Accessory
     -> SyntehsisItem
     -> BattleUseItem -> HealingItem
                      -> ThrowingItem -> ThrowsAsAttackItem

Söylemeye gerek yok, dağınık olmaya başladı ve bunlar birden fazla tip olması gereken öğelere kolay bir çözüm değildi (yani bazı ekipman madde sentezinde kullanılır, bazı ekipmanlar atılabilir, vb.)

Sonra refactor ve temel öğe sınıfına işlevsellik yerleştirmeye çalıştı. Ama sonra Öğe'nin bir sürü kullanılmamış / gereksiz veriye sahip olduğunu belirtiyordum. Şimdi mimarlık gibi bir bileşen yapmaya çalışıyorum, en azından diğer oyun sınıflarıma denemeden önce öğelerim için.

Şu anda bileşen kurulumu için düşündüğüm şey:

Çeşitli bileşenler (yani bir ekipman bileşeni yuvası, bir iyileştirme bileşeni yuvası, vb yanı sıra rastgele bileşenler için bir harita) için yuvaları olan bir temel öğe sınıfı var böyle bir şey:

class Item
{
    //Basic item properties (name, ID, etc.) excluded
    EquipmentComponent* equipmentComponent;
    HealingComponent* healingComponent;
    SynthesisComponent* synthesisComponent;
    ThrowComponent* throwComponent;
    boost::unordered_map<std::string, std::pair<bool, ItemComponent*> > AdditionalComponents;
} 

Tüm öğe bileşenleri temel bir ItemComponent sınıfından miras alır ve her bir Bileşen tipi motora bu işlevselliğin nasıl uygulanacağını bildirmekten sorumludur. yani HealingComponent, savaş mekaniğine öğeyi iyileştirici bir öğe olarak nasıl kullanacağını söylerken, ThrowComponent savaş motoruna öğeyi atılabilir bir öğe olarak nasıl ele alacağını söyler.

Harita, temel öğe bileşenleri olmayan rastgele bileşenleri depolamak için kullanılır. Öğe Kapsayıcısı ItemComponent yönetmek veya harici bir kaynak tarafından yönetiliyor olup olmadığını belirtmek için bir bool ile eşleştiriyorum.

Buradaki fikrim, oyun motorum tarafından kullanılan temel bileşenleri önceden tanımladığım ve ürün fabrikamın, öğenin gerçekte sahip olduğu bileşenleri atayacağıydı, aksi takdirde null. Harita genellikle komut dosyaları tarafından eklenecek / tüketilecek keyfi bileşenler içerecektir.

Sorum şu: Bu iyi bir tasarım mı? Değilse, nasıl geliştirilebilir? Tüm bileşenleri haritaya gruplandırmayı düşündüm, ancak çekirdek öğe bileşenleri için dize indeksleme kullanmak gereksiz görünüyordu

Yanıtlar:


8

Çok makul bir ilk adım gibi görünüyor.

Genelleştirme ("ek bileşenler" haritası) ve arama performansının (sabit kodlu üyeler) bir kombinasyonunu tercih edersiniz, bu da bir ön optimizasyon olabilir - dize tabanlı genel verimsizliğe ilişkin noktanız arama iyi yapılmış, ancak bileşenleri karma için daha hızlı bir şeyle endekslemeyi seçerek bunu hafifletebilirsiniz. Bir yaklaşım, her bileşen türüne benzersiz bir tür kimliği (aslında hafif özel RTTI uyguluyorsunuz ) ve buna dayalı bir dizin vermek olabilir.

Ne olursa olsun, Item nesnesi için herhangi bir bileşeni (sabit kodlu olanları ve ek olanları) tek tip bir şekilde sormanıza izin veren genel bir API'yi göstermenizi öneririm. Bu, tüm kod bileşeni istemcilerini yeniden düzenlemeye gerek kalmadan, sabit kodlanmış / sabit kodlanmamış bileşenlerin temel temsilini veya dengesini değiştirmeyi kolaylaştıracaktır.

Ayrıca, sabit kodlu bileşenlerin her birinin "sahte" no-op sürümlerini sağlamayı ve bunların her zaman atanmalarını sağlamayı düşünebilirsiniz - daha sonra işaretçiler yerine referans üyelerini kullanabilirsiniz ve hiçbir zaman NULL işaretçisi kontrol etmeniz gerekmez. sabit kodlanmış bileşen sınıflarından biriyle etkileşim kurmadan önce. Bu bileşenin üyeleriyle etkileşimde bulunmak için dinamik gönderim maliyetine katlanacaksınız, ancak bu, işaretçi üyeleriyle bile gerçekleşecektir. Bu daha çok bir kod temizliği meselesidir, çünkü performans etkisi her durumda ihmal edilebilir olacaktır.

İki farklı ömür boyu kapsamın olması harika bir fikir değil (başka bir deyişle, ek bileşen haritasında bulunan boolün harika bir fikir olduğunu düşünmüyorum). Sistemi karmaşıklaştırır ve yıkım ve kaynak tahliyesinin çok belirleyici olmayacağını ima eder. Bir ömür boyu yönetim stratejisini veya diğerini seçtiyseniz bileşenlerinizin API'sı çok daha açık olurdu - varlık bileşen ömrünü yönetir veya bileşenlerin gerçekleştirdiği alt sistem yapar (ikincisini tercih ederim çünkü dış bileşenle daha iyi eşleşir Bir sonraki tartışacağım yaklaşım).

Yaklaşımınızla gördüğüm en büyük dezavantaj, aslında her zaman en iyi tasarım olmayan "varlık" nesnesindeki tüm bileşenleri bir araya topladığınızdır. Gönderen benim İlgili cevap başka bileşen tabanlı soruya:

Büyük bir bileşen haritası ve oyun nesnesindeki bir update () çağrısı kullanma yaklaşımınız oldukça düşük optimaldir (ve bu tür sistemleri ilk inşa edenler için ortak bir tuzaktır). Güncelleme sırasında çok zayıf bir önbellek tutarlılığı sağlar ve eşzamanlılıktan ve aynı anda büyük veri veya davranış yığınlarının SIMD stili işlemine yönelik trendden yararlanmanıza izin vermez. Oyun nesnesinin bileşenlerini güncellemediği bir tasarım kullanmak genellikle daha iyidir, aksine bileşenin kendisinden sorumlu alt sistem hepsini bir kerede günceller.

Bileşenleri öğe varlığında (yine tamamen kabul edilebilir bir ilk adım) depolayarak aynı yaklaşımı esas alıyorsunuz. Keşfedebileceğiniz şey, performansı hakkında endişelendiğiniz bileşenlere erişimin büyük kısmının yalnızca bunları güncellemektir ve bileşenlerin önbelleğe uyumlu bir şekilde tutulduğu bileşen organizasyonuna daha dıştan takma bir yaklaşım kullanmayı seçerseniz ihtiyaçlarını en iyi anlayan bir alt sistem tarafından verimli, (kendi etki alanları için) veri yapısını daha iyi, daha paralel hale getirilebilir güncelleme performansı elde edebilirsiniz.

Ama bunu sadece gelecekteki bir yön olarak düşünecek bir şey olarak belirtiyorum - kesinlikle bunu aşırıya kaçmak istemiyorsanız; sürekli yeniden düzenleme yoluyla kademeli bir geçiş yapabilir veya mevcut uygulamanızın ihtiyaçlarınızı mükemmel bir şekilde karşıladığını ve bunun üzerinde tekrarlamaya gerek olmadığını keşfedebilirsiniz.


1
+1, Item nesnesinden kurtulmayı önerdiği için. Önde daha fazla çalışma olsa da, daha iyi bir bileşen sistemi üretecek.
James

Yeni topiuc başlatmam gerekip gerekmediğinden emin olmak için birkaç sorum daha vardı, bu yüzden önce burada deneyeceğim: Öğe sınıfım için, evert çerçeve (hatta yakın) diyeceğim hiçbir yöntem yok. Grafik alt sistemlerim için tavsiyelerinizi alacağım ve tüm nesneleri sistem altında güncel tutacağım. Diğer sorum, bileşen kontrollerini nasıl ele alacağım? Örneğin, bir öğeyi X olarak kullanıp kullanamayacağımı görmek istiyorum, bu yüzden doğal olarak öğenin X'i gerçekleştirmek için gereken bileşene sahip olup olmadığını kontrol ederdim. Bunu yapmanın doğru yolu var mı? Cevabınız için tekrar teşekkürler
user127817
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.