Bileşen tabanlı bir sistemde güçlendirme yapmak


29

Ben sadece başımı bileşen tabanlı tasarım etrafında almaya başladım. Bunu yapmanın "doğru" yolunun ne olduğunu bilmiyorum .

İşte senaryo. Oyuncu bir kalkan takabilir. Kalkan oyuncuya kabarcık şeklinde çekilir, ayrı bir çarpışma şekline sahiptir ve oyuncunun alandaki etkilerinden aldığı hasarı azaltır.

Böyle bir kalkan, bileşen tabanlı bir oyunda nasıl tasarlanır?

Kafamın karıştığı yer, kalkanın kendisiyle ilişkili üç bileşene sahip olduğu.

  • Hasar azaltma / filtreleme
  • Bir sprite
  • Bir çarpıştırıcı.

Daha da farklı hale getirmek için, kalkan varyasyonları, hepsi bileşen olabilecek daha fazla davranışa sahip olabilir:

  • oyuncu maksimum sağlık artırmak
  • sağlık rejimi
  • mermi sapması
  • vb

  1. Bunu düşünüyor muyum? Kalkan sadece süper bir bileşen mi olmalı?
    Bunun yanlış bir cevap olduğunu düşünüyorum. Öyleyse, bunun gideceğiniz yol olduğunu düşünüyorsanız lütfen açıklayınız.

  2. Kalkan, oyuncunun yerini izleyen kendi varlığı mı olmalı?
    Hasar filtrelemenin uygulanmasını zorlaştırabilir. Aynı zamanda, bağlı bileşenler ile varlıklar arasındaki çizgileri bulanıklaştırır.

  3. Kalkan, diğer bileşenleri barındıran bir bileşen midir?
    Böyle bir şeyi hiç görmedim veya duymadım, ama belki de yaygındır ve henüz yeterince derin değilim.

  4. Kalkan, oynatıcıya eklenen bir dizi bileşen mi olmalı?
    Muhtemelen diğerlerini yönetmek için ekstra bir bileşen ile, örneğin hepsi bir grup olarak çıkarılabilir. (kazara hasar azaltma bileşeninin arkasında bırakın, bu şimdi eğlenceli olurdu).

  5. Daha fazla bileşen tecrübesi olan biri için açık olan başka bir şey?


Başlığınızı daha belirgin hale getirme özgürlüğünü aldım.
Tetrad

Yanıtlar:


11

Kalkan, oyuncunun yerini izleyen kendi varlığı mı olmalı? Hasar filtrelemenin uygulanmasını zorlaştırabilir. Aynı zamanda, bağlı bileşenler ile varlıklar arasındaki çizgileri bulanıklaştırır.

Düzenleme: Ayrılmış bir varlık için yeterli "özerk davranış" olmadığını düşünüyorum. Bu özel durumda, bir kalkan hedefi takip eder, hedef için çalışır ve hedefi geçemez. Bir “kalkan nesnesi” kavramıyla ilgili yanlış bir şey olmadığı konusunda hemfikir olduğum halde, bu durumda bir bileşende tam olarak uyan davranışla ilgileniyoruz. Ama aynı zamanda tamamen mantıksal varlıkların (Dönüştürme ve İşleme bileşenlerini bulabileceğiniz tamamen gelişmiş varlık sistemlerinin aksine) savunucusuyum.

Kalkan, diğer bileşenleri barındıran bir bileşen midir? Böyle bir şeyi hiç görmedim veya duymadım, ama belki de yaygındır ve henüz yeterince derin değilim.

Farklı bir bakış açısıyla görün; bir bileşen eklemek, başka bileşenler de ekler ve çıkarıldıktan sonra, ek bileşenler de gider.

Kalkan, oynatıcıya eklenen bir dizi bileşen mi olmalı? Muhtemelen diğerlerini yönetmek için ekstra bir bileşen ile, örneğin hepsi bir grup olarak çıkarılabilir. (kazara hasar azaltma bileşeninin arkasında bırakın, bu şimdi eğlenceli olurdu).

Bu bir çözüm olabilir, yeniden kullanımı teşvik eder, ancak daha fazla hataya açıktır (örneğin, bahsettiğiniz konu için). Bu mutlaka kötü değil. Deneme ve yanılma ile yeni yazım kombinasyonları bulabilirsiniz :)

Daha fazla bileşen tecrübesi olan biri için açık olan başka bir şey?

Biraz daha ayrıntılı olacağım.

Bir işletmenin ne zaman eklendiğine bakmadan bazı bileşenlerin nasıl öncelik kazanması gerektiğini fark ettiğinize inanıyorum (bu, diğer sorunuza da cevap verecektir).

Ayrıca mesaj tabanlı iletişim kullandığımızı varsayacağım (tartışma uğruna, şu an için bir yöntem çağrısı üzerinden bir soyutlama).

Bir kalkan bileşeni "her takıldığında", kalkan bileşeni mesaj işleyicileri belirli (daha yüksek) bir sırayla zincirlenir.

Handler Stage    Handler Level     Handler Priority
In               Pre               System High
Out              Invariant         High
                 Post              AboveNormal
                                   Normal
                                   BelowNormal
                                   Low
                                   System Low

In - incoming messages
Out - outgoing messages
Index = ((int)Level | (int)Priority)

"Stats" bileşeni, In / Invariant / Normal dizinine bir "hasar" mesajı işleyicisi yükler. Bir "hasar" mesajı her alındığında, HP'yi "değer" miktarıyla azaltın.

Oldukça standart davranış (ne olursa olsun, bazı doğal hasar direnci ve / veya ırksal özellikler koyun).

Ekran bileşeni, Giriş / Ön / Yüksek indeksine "hasar" mesajı iletici kurar.

Every time a "damage" message is received, deplete the shield energy and substract
the shield energy from the damage value, so that the damage down the message
handler pipeline is reduced.

damage -> stats
    stats
        stats.hp -= damage.value

damage -> shield -> stats
    shield
        if(shield.energy) {
            remove_me();
            return;
        }
        damage.value -= shield.energyquantum
        shield.energy -= shield.energyquantum;

     stats
        stats.hp -= damage.value

Bunun oldukça esnek olduğunu görebilirsiniz, ancak bileşen etkileşimi tasarlanırken dikkatli bir planlama yapılmasını gerektirse de, ileti işleme boru hattı bileşeni ileti olayı işleyicilerinin hangi bölümüne yüklendiğini belirlemeniz gerekir.

Mantıklı? Daha fazla ayrıntı ekleyebilir miyim?

Düzenleme: Birden fazla bileşen örneği ile ilgili (iki zırh bileşeni). Toplam örnek sayımını yalnızca bir varlık örneğinde (bu, bileşen başına düşen durumu öldürür) izleyebilir ve yalnızca ileti olay işleyicileri eklemeye devam edebilir veya bileşen kaplarınızın çoğaltılmış bileşen türlerine önceden izin verdiğinden emin olabilirsiniz.


Herhangi bir sebep göstermeden ilk soruya "Hayır" cevabını verdiniz. Başkalarına öğretmek, herhangi bir kararın arkasındaki mantığı anlamalarına yardımcı olmakla ilgilidir. IMO, RL'de bir kuvvet alanının kendi vücudunuzdan ayrı bir "fiziksel varlık" olacağı gerçeği, kodda ayrı bir varlık olmasına izin vermek için yeterlidir. Bu rotaya gitmenin neden kötü olduğunu önermek için iyi nedenler önerebilir misiniz?
Mühendis

@Hayır, hiçbir şekilde kimseye bir şey öğretmeye çalışmıyorum, konuyla ilgili bildiklerimi paylaşmaya çalışmıyorum. Bununla birlikte, bu hoş olmayan olumsuz oyu kaldıracak olan "hayır" ın arkasına bir mantık ekleyeceğim:
Raine,

Özerklik noktanız mantıklı. Ancak şunu not edin: "Bu durumda davranışla uğraşıyoruz". Gerçek - tamamen ayrı bir fiziksel nesne içeren davranış (kalkan çarpışma şekli). Benim için, bir varlık bir fizik bedenine (veya örneğin eklemlerle bağlanmış bileşik beden kümesine) bağlanır. Bunu nasıl uzlaştırırsın? Benim açımdan, sadece oyuncu bir kalkan kullandığında devreye girecek olan "sahte" bir fiziksel armatür eklemekten rahatsızlık duyardım. IMO esnek olmayan, tüm varlıklar arasında korumak zor. Ayrıca düşünün, kalkan kayışlarının ölümden sonra bile kalkanlarını korudukları bir oyun (Dune).
Mühendis

Hayır, varlık sistemlerinin çoğunluğu hem mantıksal hem de grafikle ilgili bileşenlere sahiptir, bu nedenle, bu durumda, bir kalkan için bir varlık olması kesinlikle makul olur. Tamamen mantıksal varlık sistemlerinde, “özerklik”, bir nesnenin ne kadar karmaşık olduğu, bağımlılıkları ve kullanım ömrünün ürünüdür. Sonunda, gereksinim kraldır - ve bir varlık sisteminin ne olduğu konusunda gerçek bir fikir birliği olmadığı düşünüldüğünde, projeye özel çözümler için bolca yer var :)
Raine

@deft_code, cevabımı geliştirebilirsem lütfen bana bildirin.
Raine

4

1) Bunu düşünmüyor muyum? Kalkan sadece süper bir bileşen mi olmalı?

Belki, kodunuzun ne kadar tekrar kullanılabilir olmasını istediğinize ve mantıklı olup olmadığına bağlıdır.

2) Kalkan, oyuncunun yerini izleyen kendi varlığı olmalıdır mı?

Bu kalkan, bir aşamada bağımsız olarak dolaşabilecek bir yaratık olmadığı sürece olmaz.

3) Kalkan, diğer bileşenleri barındıran bir bileşen olmalı mı?

Bu varlık gibi çok geliyor, bu yüzden cevap hayır.

4) Blendaj, oynatıcıya eklenen bir dizi bileşen mi olmalı?

Olasıdır.

"Hasar azaltma / filtreleme"

  • çekirdek kalkan bileşeni işlevselliği.

"Bir sprite"

  • varlığınıza başka bir SpriteComponent ekleyememenizin bir nedeni var mı?

"Bir çarpıştırıcı"

  • Başka birine ihtiyacın olduğundan emin misin? Bu senin fizik motoruna bağlı. Karakter varlığının ColliderComponent'ına bir mesaj gönderebilir ve şeklini değiştirmesini isteyebilir misiniz?

"Oyuncu maksimum sağlık, sağlık rejimi, mermi sapması vb."

  • diğer eserler bunu yapabilir (kılıçlar, botlar, yüzükler, büyü / iksirler / ziyaret tapınakları vb.) bu yüzden bunlar bileşen olmalıdır.

3

Bir kalkan bir şekilde fiziksel bir varlık, başka herhangi bir farkı yoktur fiziksel çevrenizdeki çevreler varlığın, örneğin bir insansız (aslında, kendisi kalkan bir tür olabilir ve hangi!). Öyleyse kalkanı ayrı bir mantıksal varlık yapın (böylece kendi bileşenlerini tutmasına izin verin).

Kalkanınıza birkaç bileşen verin: çarpışma biçimini temsil eden bir Fiziksel / Mekansal bileşen ve her oyuncuya her seferinde arttırılmış veya azaltılmış hasar (örn. Oyuncu karakteriniz) uygulayacağı bazı varlıklara referansta bulunan bir DamageAffector bileşeni DamageAffector cihazını tutarak hasar alır. Böylece oyuncu "vekaleten" zarar alıyor.

Kalkanın pozisyonunu her kene oynatıcının pozisyonuna getirin. (Bunu yapan yeniden kullanılabilir bir bileşen sınıfı yazın: bir kez yazın, birçok kez kullanın.)

Örneğin, kalkan varlığını oluşturmanız gerekecektir. Bir powerup toplama üzerinde. Yeni varlıkları ortaya çıkaran bir tür varlık bileşeni olan Yayıcı adındaki genel bir kavramı kullanıyorum (genellikle referans aldığı bir EntityFactory kullanarak). Yayıcıyı bulmaya karar vereceğiniz yer size bağlıdır - örneğin. güç kaynağına yerleştirin ve güç toplanırken tetiklemesini sağlayın.


Kalkan, oyuncunun yerini izleyen kendi varlığı mı olmalı? Hasar filtrelemenin uygulanmasını zorlaştırabilir. Aynı zamanda, bağlı bileşenler ile varlıklar arasındaki çizgileri bulanıklaştırır.

Mantıksal alt bileşenler (Mekansal, AI, Silah yuvaları, Giriş işleme vb.) Ve fiziksel alt bileşenler arasında ince bir çizgi var. Ne tür bir varlık sistemine sahip olduğunuzu güçlü bir şekilde tanımladığından, hangi tarafa dayanacağınıza karar vermeniz gerekir. Benim için, Varlığımın Fizik alt bileşeni fizik-hiyerarşik ilişkileri (vücuttaki uzuvlar gibi - düşünen senaryo düğümleri gibi) ele alırken, yukarıda belirtilen mantık denetleyicileri genellikle varlık bileşenleriniz tarafından temsil edilenlerdir - bunlar bireysel fiziksel "demirbaşlar".


3

Kalkan, diğer bileşenleri barındıran bir bileşen midir?

Belki başka bileşenleri barındırmaz, ancak alt bileşenlerin ömrünü kontrol eder. Yani bazı kaba sözde kodda, müşteri kodunuz bu "kalkan" bileşenini ekleyecektir.

class Shield : Component
{
    void Start() // happens when the component is added
    {
        sprite = entity.add_component<Sprite>( "shield" );
        collider = entity.add_component<Collider>( whatever );
        //etc
    }

    void OnDestroy() // when the component is removed
    {
        entity.remove_component( sprite );
        entity.remove_component( collider );
    }

    void Update() // every tick
    {
        if( ShouldRemoveSelf() ) // probably time based or something
            entity.remove_component( this );
    }
}

Cevabında ne thisanlama geldiği belli değil . Is thisShield bileşenine atıfta ya da kalkan kullanıyor tüzel kişi ise ana anlama geliyordu? Karışıklık benim suçum olabilir. "Bileşen tabanlı" biraz belirsizdir. Bileşen tabanlı varlıklar sürümümde, varlık basit bir şekilde kendi asgari işlevselliğine (nesne adı, etiketler, mesajlaşma vb.) Sahip bir bileşen kabıdır.
deft_code

Kullanırsam gameObjectya da bir şey yaparsam daha az kafa karıştırıcı olurdu . Bu, mevcut oyun nesnesine / varlığa / bileşenlere ne olursa olsun referanstır.
Tetrad

0

Bileşen sisteminiz komut dosyası oluşturmaya izin veriyorsa, kalkan bileşeni "efekt" parametresi için yalnızca bir komut dosyasını çağıran neredeyse süper bir bileşen olabilir. Bu şekilde, kalkanlar için tek bir bileşenin sadeliğini korursunuz ve kalkan tanımlarına göre kalkanlara beslenen özel script dosyalarına gerçekte yaptığı şeyin tüm mantığını kaldırıyorsunuz.

Moveable bileşenim için benzer bir şey yapıyorum, keyreation betiği (motorumda betiğin alt sınıfı) olan bir alanı kapsıyor. gibi tempalte tanım dosyamda basitçe böyle bir şey yapabilirim

camera template
    moveable
    {
        keyreaction = "scriptforcameramoves"

    }  

player template
    moveable
    {
        keyreaction = "scriptfroplayerkeypress"

    }  

daha sonra mesaj kaydı sırasında taşınır bileşenimde scriptler Do metodunu kaydetiyorum (C # koduyla)

Owner.RegisterHandler<InputStateInformation>(MessageType.InputUpdate, kScript.Do);

Tabii ki bu, RegisterHandler’imin aldığı işlevlerin desenini takip eden Do yöntemime dayanıyor. Bu durumda onun (IComponent gönderen, ref tipi argümanı)

bu yüzden benim "script" (benim durumumda da C # sadece runime derlenmiş) tanımlar

 public class CameraMoveScript : KeyReactionScript
{
 public override void Do(IComponent pSender, ref InputStateInformation inputState)
 {
    //code here
 }
}

ve temel sınıfım KeyReactionScript

public class KeyReactionScript : Script
{
      public virtual void Do(IComponent pSender, ref InputStateInformation inputState);
}

daha sonra bir giriş bileşeni, böyle bir tür olan MessageTypes.InputUpdate türünde bir ileti gönderdiğinde

 InputStateInformation myInputState = InputSystem.GetInputState();
 SendMessage<InputStateInformation>(MessageTypes.InputUpdate, ref myInputState);

Komut dosyasında bu mesaja ve veri türüne bağlı olan yöntem kovulacak ve tüm mantığı kullanacaktır.

Kod motoruma oldukça özel, ancak her durumda mantık işlevsel olmalı. Bileşen yapısını basit ve esnek tutmak için bunu birçok tür için yapıyorum.

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.