Bir varlık sistemindeki birçok hareket kaynağı


9

Varlık sistemleri fikrinde oldukça yeniyim, bir sürü şey okudum (en faydalısı, bu harika blog ve bu cevap ).

Gerçi, bir nesnenin konumunu tanımsız sayıda kaynakla manipüle edebilmek kadar basit bir şeyi anlamakta biraz zorluk çekiyorum.

Yani, pozisyon bileşenine sahip varlığım var. Daha sonra oyunda bu varlığa belirli bir mesafeyi belirli bir zamanda hareket ettirmesini söyleyen bir olay var.

Bu olaylar herhangi bir zamanda olabilir ve konum ve zaman için farklı değerlere sahip olacaktır. Sonuç, bir araya getirilmeleri.

Geleneksel bir OO çözümünde, MoveBymesafe / zamanı içeren bir çeşit sınıfım ve oyun nesnesi sınıfımın içinde yer alan bir dizi var. Her bir kareyi, tümüyle yineleyip MoveBy, pozisyona uygularım. A MoveBybitiş zamanına ulaştıysa, diziden kaldırın.

Varlık sistemi ile, bu tür davranışları nasıl tekrarlamam gerektiği konusunda biraz kafam karıştı.

Bunlardan sadece bir tanesi olsaydı, onları bir araya getirebilmek yerine, oldukça basit olurdu (inanıyorum) ve şöyle bir şey olurdu:

PositionComponent kapsamak x, y

MoveByComponent kapsamak x, y, time

Entityhem a hem de PositionComponentbirMoveByComponent

MoveBySystembu bileşenlerin her ikisine de sahip olan bir varlığı arar MoveByComponentve PositionComponent. Öğesine timeulaşıldığında, bileşeni bu varlıktan kaldırır.

Aynı şeyi birçok hamle ile nasıl yapacağım konusunda biraz kafam karıştı.

İlk düşüncelerim:

PositionComponent, MoveByComponentyukarıdaki ile aynı

MoveByCollectionComponentMoveByComponents dizisi içeren

MoveByCollectionSystema PositionComponentve a içeren bir varlığı arar MoveByCollectionComponent, MoveByComponentiçindeki s aracılığıyla yinelenir , gerektiğinde uygulanır / kaldırılır.

Sanırım bu, aynı bileşenin birçoğuna sahip olmak ve karşılık gelen bir sistemin her biri üzerinde hareket etmesini istemek için daha genel bir sorundur. Varlıklarım bileşenlerini bileşen türü -> bileşeninin bir karması içinde içerir, bu nedenle varlık başına belirli bir türde yalnızca 1 bileşen bulunur.

  1. Buna bakmanın doğru yolu bu mu?

  2. Bir işletmenin her zaman belirli bir türde tek bir bileşeni olmalı mıdır?


1
Kulağa MoveByişlevsellik gibi geliyor sadece bir hız? Doğru yoldaymış gibi geliyor. İkinci sorunuz için, varlık / bileşen sistemlerinin birçok farklı uygulaması vardır. Bağladığım cevabımda anlatılan cevap, verilen türde sadece bir bileşene sahip olacaktı.
MichaelHouse

Bir çeşittir, ancak fark, bu hızın sadece bir kereden diğerine geçerli olmasıdır ve birçoğu bir kerede birleştirilebilir. Sanırım biraz güvenceye ihtiyacım vardı, geçmişte oyunlarım için sıkı (anal, neredeyse) OO oldum - bu yıllar sonra aynı projede üretim hızımızı sakatladı - ve bu korkunç bir şekilde yabancı bölge;) . Bu arada diğer gönderide büyük cevap, bazı şeyleri temizlemeye yardımcı oldu
Yapışkan

Bunu şu şekilde yapıyorum: MobileBehaviorComponent'e klavye tıklaması veya mobil cihazların bir yere taşınması gerektiğini düşünen AI üzerinde MobileBehaviorComponent'in bir yere taşınması gerektiğini (Mobile eylemleri için içinde FSM var) depolayacağını söyleyen PlayerInputComponent ve AIInputComponent (veya sistemleri) var. ve bazı sistem onu ​​hareket ettirir. Ayrıntı düzeyiniz çok fazla, Transform, Model, Light, Mob gibi daha üst düzey bileşenlerle her şey aynı şekilde çalışıyor. Ayrıca bileşenleri kaldırmak için asla gerekli - ben sadece ortadan kaybolamaz böylece oyun nesnesini açıklayan bir şey gibi onları düşünüyorum.
Kikaimaru

Bu özel MoveBy örneği sadece bir örnektir. Soru daha çok şeyleri bu şekilde nasıl birleştirdiğinizle ilgili idi. Özellikle '5 saniyede x = 5 ve y = 6 ile hareket et' 'demem gerekirse, aynı anda x = 10 y = 2 ile 10 saniyede hareket et' dersem, bunu nasıl yapardım?
Yapışkan

"Birleştirilmiş" demekle ne demek istiyorsun? Hız eklemek gibi mi? Yani eğer bileşik move x by 10 in 2 secondsve move x by -10 in 2 secondsvarlık kıpırdamadan kalkar mısın?
Tom Dalling

Yanıtlar:


6

Senaryonuz için genellikle bir oyun nesnesine üç bileşen ekliyoruz:

  1. TransformComponent (konum, yön, ölçek)
  2. VelocityComponent (hız, yön)
  3. ControllerComponent

Oyun nesneleri, açıkladığınız gibi bir yol boyunca hareket etme gibi bir tür AI işlevselliğine ihtiyaç duyduğunda, bileşen listesine bir AIController atarız. AIControllers, bir Davranış Ağacına adım atan bir sarıcıdan başka bir şey değildir. Davranış ağacı, oyun nesnesinin gerçekleştirmesini istediğiniz gerçek işlevselliği tasarladığımız yerdir:

BehaviorTree* tree(new SequentialNode());
tree->addChild(new MoveToNode(x,y,z));
tree->addChild(new WaitNode(30));
tree->addChild(new MoveToNode(a,b,c));
tree->addChild(new WaitNode(30));
gameObject->addComponent(new AIController(tree));

AI alt sistemi, AIController'ları yönetir ve böylece alt sistem, denetleyiciyi Davranış Ağacı'na adım atar. MoveToNode () mevcut konuma / yönlendirmeye bakar, yapıcı argümanlarına dayanarak gitmek istediğiniz yere bir yön vektörü ve hızı hesaplar ve hız bileşenindeki değerleri ayarlar. Hareket sistemi, hareket bileşenlerini değerlerle okumaktan ve fizik uygulamaktan ve böylece pozisyonu / yönlendirmeyi buna göre güncellemekten sorumludur.

Yukarıdaki kod, bir oyun nesnesini spawn konumundan dünya uzayında x, y, z'ye taşır, daha sonra en az 30 saniye bekler, ardından oyun nesnesini a, b, c konumuna taşır ve 30 saniye daha bekler. Bekleme sona erdiğinde, davranış dizisi tamamlanmıştır, bu yüzden baştan tekrar eder.

Bu, AI alt sisteminde yer alan tüm kendi ihtiyacınız olan AI işlevlerini, Varlık alt sisteminize minimum etkisi olacak şekilde kolayca tanımlamanızı sağlar. Ayrıca varlık sistemi bileşen listenizi çok fazla ayrıntı düzeyi olmadan yalın tutmanıza da olanak tanır.


1

Bir seçenek, tasarımınıza denetleyiciler eklemektir. Varlıklar pozisyonu temsil etmek için verilere sahiptir (motorumda önceki pozisyonları da hatırlayan verilere sahiptirler, bu yüzden hız vektörünü ve taşınıyor veya ışınlanıyorsa bilmiyorum), ancak fizik veya AI. Denetleyiciler varlıkları taşır ve aynı varlığı etkileyen birçok denetleyiciniz veya çeşitli varlıkları etkileyen bir denetleyiciniz olabilir.

Örneğin: run () yöntemiyle bir temel Controller sınıfı oluşturun veya adından hoşlanmıyorsanız düşünün (), update () veya tick () çağırın. Sonra ondan devralır ve bir MoveController, NPCController, PlayerInputController (player varlığı için), PhysicController; sonra run () yöntemini uygularsınız. Ben MoveByComponent Varlık değil MoveController koymak istiyorum.

Bu Kontrolörler, bir Varlığa özgü veriler barındırıyorsa, her bir Varlık tarafından başlatılabilir. Yeniden kullanılabilirler için yok edilebilir veya sıfırlanabilirler. Ayrıca, bir RTE oyununda bir grup varlığı taşımak için bir Denetleyici kullanabilirsiniz, örneğin, çeşitli birimleri grup olarak taşımanız gerekiyorsa, her bir birimin kontrolörüne sahip olması oyun performansına zarar verebilir, o zaman tüm birimleri atayabilirsiniz bir GroupController veya LegionController'a aktarın ve birimleri organize bir grubun parçası olarak taşımasına izin verin. Dövüş yaparken, oyun bireysel birim davranışına izin veriyorsa ve muhtemelen çoğu oyun bunu yapıyorsa, bir UnitController'a geçmeniz gerekecek, ancak bunu en baştan yapmak gerektiğinde yapmak daha iyidir.

Gelişmekte olan oyunumda, bir yolu takip eden objeleri hareket ettiren bir MoveController var, her NPC ve oyuncu karakteri için bir MoveController var. Bazen oyuncunun itebileceği kutular veya kaya için bir tane oluşturulur. PhysicController, kendisine atanan tüm varlıkların konumlarını kontrol edecek tek bir örnek, eğer bazı bir varlık başka bir atanmış varlığı çarpıştırıyorsa, her ikisinin sonuç konumu hesaplanır (aslında bundan daha fazlasını yapar, ancak fikri alırsınız). NPCController, her NPC için bir örnek olan AI'dır. NPC'nin durumunu kontrol eder ve nereye taşınacağına karar verir, ardından NPC'yi hareket ettiren bir MoveController yolunu iter. Kontrolörler bir önceliğe sahiptir, bu yüzden siparişlerini önceden belirleyebilirim, PhysicController en son çalıştırılır.

Denetleyicileri savunuyorum ama tek "doğru" seçenek değil. Örneğin, Cafu motorunda Varlığın kendisinde think () yöntemine sahip bir Entity arabirimini hatırlıyorum, sınıfın kullanıcısı Entity'den miras almalı ve think () uygulamalıdır, CompanyBot adlı türetilmiş bir sınıfı hatırlıyorum (örnekle birlikte gelir) oyun) bu yöntemde bazı çarpışma kontrolü yapan "düşün" olarak adlandırdığımız için AI kodunun da orada olması bekleniyor. NeoAxis motoru (son baktığımda) yapay zeka ve fiziğin varlıklardan ayrılmış olmasına rağmen.

Dinlediğim bir Denetleyici modeli var. Belki de aramalısınız ve muhtemelen tam olarak burada bahsettiğim şey değil, aynı zamanda iyi bir çözüm gibi geliyor.


Temelde şu anda sahip olduğumuz OO tasarımı. Türevleri (Karakter, Canavar) vb. Olan bir Varlık, neredeyse 2 yıldır bu oyunda tam zamanlı çalışan bir ekibimize liderlik ediyorum ve herkes irade değiştirerek, korkunç, korkunç bir hale geldi codebase - ve yeni özelliklerin gönderilmesi utanç verici bir şekilde uzun zaman almaya başlıyor. Varlık Sistemi fikri tam olarak aradığım şey gibi görünüyor , bu yüzden cevabınız oldukça alakalı olmasa da, sorunun üst kısmındaki bağlantıları kendiniz okumalı, size yardımcı olup olamayacaklarını görmelisiniz :)
Yapışkan

@ Yapışkan Düğüm Sistemi artı Bileşenlerden oluşan Varlığın, daha az gelişmiş bir versiyona benzeyen önerilen kontrolörler yaklaşımımdan farklı gerekli sistemleri temsil etmenin akıllı bir yolu olduğunu itiraf etmeliyim. Sonuçta benim cevabıma gerçekten ihtiyacın yok.
Hatoru Hansou

Telaşa gerek yok. OO yolunun avantajları var, ama işler çirkin, hızlı oluyor
Yapışkan
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.