Davranış Ağaçlarını Önleme


25

Kafamı davranış ağaçlarının etrafına sokmaya çalışıyorum, bu yüzden bazı test kodları çıkarıyorum. Mücadele ettiğim bir şey, daha yüksek önceliğe sahip bir şey ortaya çıktığında, şu anda çalışan bir düğümü nasıl önleyeceğimizdir.

Bir asker için aşağıdaki basit, hayali davranış ağacını göz önünde bulundurun:

görüntü tanımını buraya girin

Bazı kenelerin geçtiğini ve yakınlarda bir düşman bulunmadığını, askerin çimlerde durduğunu ve bu nedenle Otur aşağı düğümü yürütmek için seçildiğini varsayalım :

görüntü tanımını buraya girin

Şimdi Otur aşağı eyleminin yürütülmesi zaman alıyor çünkü oynatılacak bir animasyon var, bu yüzden Runningdurumu olarak geri dönüyor . Bir kene veya iki geçiyor, animasyon hala devam ediyor, ama Düşman yakın mı? durum düğümü tetikleyicileri. Şimdi , Saldırı düğümünü yürütebilmek için ASAP Oturumu aşağı düğümünü engellememiz gerekiyor . İdeal olarak, asker oturmayı bile bitiremezdi - sadece oturmaya başladıysa, animasyon yönünü tersine çevirebilirdi. Daha fazla gerçekçilik için, eğer animasyonda bir devrilme noktasını geçerse, onun yerine oturmasını ve sonra tekrar durmasını ya da tehdidine tepki göstermesi için acele etmesine izin vermeyi seçebiliriz.

Olabildiğince dene, bu tür durumlarla nasıl başa çıkılacağı konusunda rehberlik bulamadım. Son birkaç gündür tükettiğim tüm literatür ve videolar (ve çok geçti) bu konunun etrafında durmuş gibi görünüyor. Bulabildiğim en yakın şey, çalışan düğümleri sıfırlama kavramıydı, ancak bu Sit gibi düğümlere "hey, henüz bitmedi!" Deme şansı vermedi.

Belki bir tanımlama düşünce Preempt()ya Interrupt()benim taban üzerinde yöntemini Nodesınıftan. Farklı düğümler uygun gördüklerini halledebilirler, ancak bu durumda askerin en kısa zamanda ayağa kalkıp geri dönmeye çalışırdık Success. Bu yaklaşımın, tabanımın Nodediğer kavramlara ayrı ayrı koşullar kavramına sahip olmasını gerektireceğini düşünüyorum . Bu şekilde, motor sadece koşulları kontrol edebilir ve geçerse, eylemlerin yürütülmesine başlamadan önce çalışmakta olan tüm düğümleri engelleyebilir. Bu farklılaşma tespit edilmezse, motorun düğümleri ayırt etmeksizin gerçekleştirmesi gerekirdi ve bu nedenle çalışanı engellemeden önce yeni bir işlemi tetikleyebilir.

Başvuru için, aşağıda benim mevcut temel sınıflarım. Yine, bu bir anidir, bu yüzden işleri olabildiğince basit tutmaya çalıştım ve sadece ihtiyacım olduğunda ve bunu anladığımda karmaşıklığı eklemeye çalıştım.

public enum ExecuteResult
{
    // node needs more time to run on next tick
    Running,

    // node completed successfully
    Succeeded,

    // node failed to complete
    Failed
}

public abstract class Node<TAgent>
{
    public abstract ExecuteResult Execute(TimeSpan elapsed, TAgent agent, Blackboard blackboard);
}

public abstract class DecoratorNode<TAgent> : Node<TAgent>
{
    private readonly Node<TAgent> child;

    protected DecoratorNode(Node<TAgent> child)
    {
        this.child = child;
    }

    protected Node<TAgent> Child
    {
        get { return this.child; }
    }
}

public abstract class CompositeNode<TAgent> : Node<TAgent>
{
    private readonly Node<TAgent>[] children;

    protected CompositeNode(IEnumerable<Node<TAgent>> children)
    {
        this.children = children.ToArray();
    }

    protected Node<TAgent>[] Children
    {
        get { return this.children; }
    }
}

public abstract class ConditionNode<TAgent> : Node<TAgent>
{
    private readonly bool invert;

    protected ConditionNode()
        : this(false)
    {
    }

    protected ConditionNode(bool invert)
    {
        this.invert = invert;
    }

    public sealed override ExecuteResult Execute(TimeSpan elapsed, TAgent agent, Blackboard blackboard)
    {
        var result = this.CheckCondition(agent, blackboard);

        if (this.invert)
        {
            result = !result;
        }

        return result ? ExecuteResult.Succeeded : ExecuteResult.Failed;
    }

    protected abstract bool CheckCondition(TAgent agent, Blackboard blackboard);
}

public abstract class ActionNode<TAgent> : Node<TAgent>
{
}

Beni doğru yöne götürebilecek bir fikri olan var mı? Düşüncelerim doğru çizgide mi, yoksa korktuğum kadar saf mı?


Bu belgeye bir göz atmanız gerekir: burada chrishecker.com/My_liner_notes_for_spore/… burada ağacın nasıl yürüdüğünü açıklar, bir devlet makinesi gibi değil, ancak her bir kenette, reaktivite için gerçek bir püf noktasıdır. BT'nin istisnalara veya olaylara ihtiyacı olmamalıdır. Sistemlerini kendinden havuzluyorlar ve her zaman kökünden aşağı akması sayesinde tüm durumlara tepki veriyorlar. Öncelikli işleyiş böyledir, eğer yüksek öncelikli bir dış durum kontrol edilirse, oraya akar. (bazı çağrı Stop()aktif düğümleri çıkmadan önce geri arama)
v.oddou

bu aigamedev.com/open/article/popular-behavior-tree-design ayrıca çok güzel bir şekilde detaylandırılmıştır
v.oddou

Yanıtlar:


6

Kendimle aynı soruyu sorarken kendimi buldum ve bu blog sayfasının yorum bölümünde , sorunun başka bir çözümü ile ilgili olarak kısa bir sohbet ettik.

İlk şey, eşzamanlı düğümü kullanmaktır. Eşzamanlı düğüm, özel bir bileşik düğüm türüdür. Tek bir işlem düğümü tarafından takip edilen önkoşul kontroller dizisinden oluşur. İşlem düğümü 'çalışıyor' durumunda olsa bile tüm alt düğümleri günceller. (Başlaması gereken dizi düğümünün aksine, güncel çalışan alt düğümden güncelleştirmesidir.)

Ana fikir eylem düğümleri için iki dönüş durumu daha oluşturmak: "iptal" ve "iptal".

Eşzamanlı düğümde önkoşul kontrolünün başarısızlığı, çalışan eylem düğümünün iptal edilmesini tetikleyen bir mekanizmadır. Eylem düğümü uzun süre çalışan iptal etme mantığı gerektirmiyorsa, derhal 'iptal edildi' olarak geri dönecektir. Aksi halde, eylemin doğru şekilde kesilmesi için gereken tüm mantığı koyabileceğiniz 'iptal etme' durumuna geçer.


Merhaba ve GDSE'ye hoş geldiniz. Bu blogu buraya ve sonunda o bloga bağlayarak bu cevabı açabilirseniz çok iyi olur. Bağlantılar ölme eğilimindedir, burada tam olarak cevaplanması, daha kalıcı kılar. Soru şimdi 8 oy aldı, bu yüzden iyi cevap harika olurdu.
Katu

Davranış ağaçlarını sonlu durum makinesine geri getiren hiçbir şeyin iyi bir çözüm olduğunu sanmıyorum. Yaklaşımınız her devletin tüm çıkış koşullarını öngörmeniz gerektiği gibi görünüyor. Bu aslında FSM'nin dezavantajı olduğunda! BT, kökten geri dönme avantajına sahiptir, bu da açıkça bağlı bir FSM oluşturarak dolaylı olarak çıkış koşullarını açıkça yazmamızı önler.
v.oddou

5

Sanırım askerin zihin ve beden (ve başka bir şey) içine ayrıştırılabilir. Daha sonra, vücut bacaklar ve ellere ayrıştırılabilir. Daha sonra, her bölüm kendi davranış ağacına ve ayrıca genel arayüze ihtiyaç duyar - daha yüksek veya daha düşük seviyeli bölümlerden gelen istekler için.

Böylece, her bir eylemi mikro-yönetmek yerine, "vücut, bir süre oturun" veya "vücut, orada koşun" gibi anında çekilen mesajlar gönderirsiniz ve vücut animasyonları, durum geçişlerini, gecikmeleri ve diğer şeyleri yönetir sen.

Alternatif olarak, vücut bu gibi davranışları kendi başına yönetebilir. Eğer emri yoksa, "burada oturabilir miyiz?" Diye sorabilir. Daha ilginç olanı, kapsülleme nedeniyle, yorgunluk veya sersemlik gibi özellikleri kolayca modelleyebilirsiniz.

Hatta parçaları değiştirebilirsin - zombi zekasıyla fil yap, insana kanatlar ekler (farketmeyecek bile), ya da başka bir şey.

Bu şekilde ayrışma olmadan, er ya da geç, kombinatoryal patlama ile karşılaşma riski altındasınızdır.

Ayrıca: http://www.valvesoftware.com/publications/2009/ai_systems_of_l4d_mike_booth.pdf


Teşekkürler. Cevabını 3 kez okuduktan sonra anlıyorum. Bu hafta sonu bu PDF'yi okuyacağım.
Benim,

1
Bunu bir saat boyunca düşündüğümde, akıl ve beden için tamamen ayrı BT'lere sahip olmakla alt ağaçlara ayrıştırılan tek bir BT'ye (özel bir dekoratör aracılığıyla, derleme zamanı komut dosyasıyla referans verilen) ayırmak arasındaki farkı anladığımdan emin değilim. her şeyi birlikte büyük bir BT'ye bağlamak). Bana göre bunun benzer soyutlama faydaları sağlayacağı ve belirli bir işletmenin nasıl davrandığını anlamayı kolaylaştıracağı, çünkü birden fazla ayrı BT'ye bakmak zorunda kalmayacağınız görünüyor. Ancak, muhtemelen naif oluyorum.
Benim,

@ user13414 Farklılık, ağaç oluşturmak için özel komut dosyalarına ihtiyacınız olacak, yalnızca dolaylı erişimi kullanırken (yani vücut düğümü ağacına hangi nesnenin bacakları temsil ettiği ağacına sorması gerektiğinde) yeterli olabilir ve ayrıca herhangi bir ek beyin tıkanması gerektirmeyecektir. Daha az kod, daha az hata. Ayrıca, çalışma zamanında alt ağacı değiştirme (kolay) özelliğini kaybedeceksiniz. Böyle bir esnekliğe ihtiyacınız olmasa bile, hiçbir şey kaybetmezsiniz (yürütme hızı dahil).
Yağmurda Gölgeler

3

Dün gece yatakta yattığımda, sorumu yönelttiğim karmaşıklığı tanıtmadan bu konuda nasıl gidebileceğime dair bir epifiz vardı. (Zayıf olarak adlandırılmış, IMHO) “paralel” kompozitin kullanılmasını içerir. İşte ne düşünüyorum:

görüntü tanımını buraya girin

Umarım bu hala oldukça okunaklıdır. Önemli noktalar:

  • Masaya / Delay / kalk sekansı, bir paralel dizi (içinde bir dizidir bir ). Her tikta, paralel sıra, düşmanı yakın koşulu (ters çevrilmiş) de kontrol ediyor . Bir düşman yaklaşıyorsa , durum başarısız olur ve paralel dizinin tamamı da aynı şekilde gerçekleşir (hemen, çocuk sırası Sit'in altında , Gecikmeli veya Ayağa kalkarken bile )
  • başarısızlık durumunda, paralel sekansın üzerindeki seçici B kesinti ile başa çıkmak için seçici C'ye atlayacaktır . Daha da önemlisi, paralel sıra A başarıyla tamamlandıysa seçici C çalışmayacaktır.
  • seçici C daha sonra normal bir şekilde ayağa kalkarsa da, asker şu anda garip bir pozisyonda basitçe ayağa kalkacak bir pozisyondaysa, yanıltıcı bir canlandırmayı da tetikleyebilir

Sanırım bu, çalışacağımı (yakında ani olarak deneyeceğim), öngördüğümden biraz daha karışık olmasına rağmen. İşin iyi yanı, sonunda alt ağaçları tekrar kullanılabilir bir mantık parçası olarak kapatabildiğim ve bunlara birçok noktadan başvurabileceğim. Buradaki endişelerimin çoğunu hafifletecek, bu yüzden bunun uygulanabilir bir çözüm olduğunu düşünüyorum.

Tabii ki, bu konuda herhangi bir düşüncesi olan varsa duymayı çok isterim.

GÜNCELLEME : Her ne kadar bu yaklaşım teknik olarak işe yarasa da, buna ek olarak karar verdim. Çünkü ilgisiz alt ağaçların, kendi ölümlerini tetikleyebilmeleri için ağacın diğer bölümlerinde tanımlanan koşulları "bilmesi" gerekir. Alt-ağaç referanslarını paylaşmak bu acıyı hafifletmek için bir yol bulacaktır, yine de davranış ağacına bakarken ne beklediğine aykırıdır. Aslında, aynı hatayı iki kere çok basit bir başakta yaptım.

Bu nedenle, diğer rotadan aşağı ineceğim: nesne modelinde preempting için açık destek ve preemption gerçekleştiğinde farklı bir dizi eylemin yürütülmesini sağlayan özel bir bileşik. Çalışan bir şeyim olduğunda ayrı bir cevap göndereceğim.


1
Eğer gerçekten alt ağaçları tekrar kullanmak istiyorsanız, o zaman ne zaman araya gireceğinin mantığı (buradaki "yakın düşman") muhtemelen alt ağaçların bir parçası olmamalıdır. Bunun yerine, belki de sistem herhangi bir alt ağaçtan (burada B) daha yüksek öncelikli bir uyarı nedeniyle kendisini kesmesini isteyebilir ve daha sonra karakteri belirli bir standart duruma geri döndürecek olan özel olarak işaretlenmiş bir kesme düğümüne (burada C) atlar. örneğin ayakta durma. İstisna ağacı davranış istisna işleme eşdeğer bir bit.
Nathan Reed

1
Hangi uyaranın kesintiye uğradığına bağlı olarak birden fazla kesinti işleyicisi dahil edebilirsiniz. Örneğin, NPC oturuyor ve ateş almaya başlıyorsa, ayağa kalkmasını (ve daha büyük bir hedef sunmasını) istemeyebilir, daha ziyade düşük kalmasını ve gizlenmesini engelleyebilirsiniz.
Nathan Reed

@ Nathan: "İstisna kullanımı" ndan bahsettiğin komik. Dün gece düşündüğüm ilk olası yaklaşım, iki çocuğu olacak bir Preempt kompoziti fikriydi: biri normal uygulama için, diğeri ise önlenmiş uygulama için. Normal çocuk geçerse veya başarısız olursa, bu sonuç yükselir. Önceden doğan çocuk, ancak herhangi bir ön hazırlık gerçekleştiğinde kaçar. Tüm düğümlerin Preempt()ağaçta dolaşacak bir yöntemi olacaktı. Bununla birlikte, bunun gerçekten “üstesinden gelmek” için tek şey, hemen ön-üreme alt düğümüne geçecek olan ön-kompozit olacaktır.
Benim,

Sonra yukarıda ana hatlarıyla anlattığım paralel yaklaşımı düşündüm ve bu daha şık görünüyordu çünkü API için fazladan sargı gerektirmiyordu. Alt-ağaçları içine alma konusundaki amacınıza göre, karmaşıklığın ortaya çıktığı her yerde, bunun olası bir ikame noktası olacağını düşünüyorum. Sık sık birlikte kontrol edilen birkaç koşulun olduğu yer burası bile olabilir. Bu durumda, ikamenin kökü, çocukları gibi birçok koşulu olan bir dizi kompoziti olacaktır.
Benim,

Bence Subtrees, yürütmeden önce "vurmak" için gereken koşulları bilmeleri , kendilerini kendi içlerinde bulundurmaları ve çok açık ve dolaylı olmaları nedeniyle tamamen uygun olduğunu düşünüyorum. Bu daha büyük bir endişe ise, o zaman koşulları alt ağaçta tutmayınız, ancak “çağrı sitesi” nde tutunuz.
Seivan

2

İşte şimdilik çözüm bulduğum çözüm ...

  • Temel Nodesınıfımın Interruptvarsayılan olarak hiçbir şey yapmadığı bir yöntemi vardır.
  • Koşullar "birinci sınıf" yapılardır, çünkü geri dönmeleri istenir bool(bu nedenle yürütmek için hızlı olduklarını ve asla birden fazla güncellemeye ihtiyaç duymadıklarını gösterir)
  • Node bir dizi koşul, alt düğümler koleksiyonuna ayrı olarak gösterir.
  • Node.Executeönce tüm koşulları uygular ve herhangi bir durumun başarısız olması durumunda derhal başarısız olur. Koşullar başarılı olursa (veya hiçbiri yoksa), ExecuteCorealt sınıfın gerçek çalışmasını yapabilmesi için çağırır . Aşağıda göreceğiniz nedenlerden dolayı koşulların atlanmasına izin veren bir parametre var
  • Nodeayrıca koşulların izolasyon yoluyla bir CheckConditionsyöntemle yürütülmesine izin verir . Tabii ki, Node.Executeaslında sadece CheckConditionskoşulları doğrulamak için gerektiğinde çağırır
  • Benim Selectorkompozit şimdi çağırır CheckConditionso yürütülmesi için gördüğü her çocuk için. Koşullar başarısız olursa, doğrudan bir sonraki çocuğa doğru ilerler. Geçerlerse, zaten çalışan bir çocuk olup olmadığını kontrol eder. Eğer öyleyse, o çağırır Interruptve sonra başarısız olur. Bu noktada yapabileceklerinin hepsi şu anda çalışan düğümün kesme isteğine yanıt vereceği umuduyla ...
  • InterruptibleÖzel bir dekoratör olan bir düğüm ekledim , çünkü dekore edilmiş çocuğu olarak düzenli bir mantık akışı ve ardından kesintiler için ayrı bir düğüm. Normal çocuğunu yarıda kesilmediği sürece tamamlama veya başarısızlığa uğratır. Kesilirse, gerektiği kadar karmaşık bir alt ağaç olabilen kesinti işleme alt düğümünü çalıştırmaya hemen geçer.

Sonuçta benim başımdan alınan böyle bir şey:

görüntü tanımını buraya girin

Yukarıdaki nektarı toplayan ve kovana geri veren bir arı için davranış ağacıdır. Nektarı olmadığı ve bir çiçeğe yakın olmadığı zamanlarda dolaşır:

görüntü tanımını buraya girin

Eğer bu düğüm kesilemezse, asla başarısız olmaz, bu yüzden arı sürekli dolaşır. Bununla birlikte, ana düğüm bir seçici olduğundan ve önceliği yüksek çocukları olduğu için, yürütmeye uygunlukları sürekli kontrol edilir. Koşulları geçerse, seçici bir kesinti yaratır ve üstteki alt ağaç derhal "Kesildi" yoluna geçer, bu da ASAP'ı başarısızlıkla kurtarır. Elbette ilk önce başka bazı eylemler yapabilirdi, ama başağımın kefaletten başka yapacak bir şeyi yok.

Yine de, bunu soruma bağlamak için, "Kesilen" yolun, oturma animasyonunu tersine çevirmeye çalıştığını ve başarısızlığa uğrayan askerin yanmasını sağladığını hayal edebilirsiniz. Bütün bunlar daha yüksek öncelikli duruma geçişi durduracaktı ve bu tam olarak amacın buydu.

Bu yaklaşımdan mutlu olduğumu düşünüyorum - özellikle yukarıda ana hatlarını verdiğim ana parçaları - ancak dürüst olmak gerekirse, şartlar ve eylemlerin özel uygulamalarının çoğalması ve davranış ağacının animasyon sistemine bağlanması hakkında daha fazla soru soruluyor. Bu soruları henüz dile getirebileceğimden bile emin değilim, bu yüzden düşünmeye devam edeceğim.


1

"When" dekoratörünü icat ederek de aynı sorunu çözdüm. Bir koşulu ve iki çocuk davranışı var ("sonra" ve "aksi halde"). "Ne zaman" yürütüldüğünde, durumu kontrol eder ve sonucuna bağlı olarak, daha sonra / sonra çocuk çalıştırır. Durum sonucu değişirse, çalışan çocuk sıfırlanır ve diğer dallara karşılık gelen çocuk başlatılır. Çocuk yürütmeyi bitirirse, tüm "Ne zaman" yürütmeyi bitirir.

Kilit nokta, bu durumdaki ilk BT'den farklı olarak, sadece sekans başlangıcında koşulun kontrol edildiği durumda, "Zamanımın" çalıştığı sırada durumu kontrol etmeye devam etmesidir. Böylece, davranış ağacının üstü ile değiştirilir:

When[EnemyNear]
  Then
    AttackSequence
  Otherwise
    When[StandingOnGrass]
      Then
        IdleSequence
      Otherwise
        Hum a tune

Daha gelişmiş "Ne zaman" kullanımı için de, yalnızca belirli bir süre boyunca veya süresiz olarak hiçbir şey yapmayan "Bekle" eylemi tanıtmak ister (ebeveyn davranışına göre sıfırlanana kadar). Ayrıca, yalnızca bir "Ne Zaman" dalına ihtiyacınız varsa, diğeri "Başarılı" veya "Başarısız" eylemlerini içerebilir, bu saygıdeğer başarı ve başarısızlık hemen gerçekleşir.


Bu yaklaşımın BT'nin orijinal mucitlerinin aklında olanlara daha yakın olduğunu düşünüyorum. Daha dinamik bir akış kullanır, bu nedenle BT'de "çalıştırma" durumu çok nadiren kullanılması gereken çok tehlikeli bir durumdur. BT'leri her zaman kökünden geri gelme ihtimalini göz önünde bulundurarak tasarlamalıyız.
v.oddou

0

Geç kaldığım halde umarım bu yardımcı olabilir. Çoğunlukla, bunu anlamaya çalıştığım gibi kişisel olarak kendimden bir şey kaçırmadığımdan emin olmak istiyorum. Çoğunlukla bu fikri ödünç aldım Unreal, ancak bunu Decoratortemelde bir mülk yapmadan Nodeya da güçlü bir şekilde birbirine bağlı olarak, Blackboarddaha geneldir.

Bu adı verilen yeni bir düğüm türü tanıtacak Guardbir kombinasyonundan gibidir Decoratorve Compositebir sahiptir condition() -> Resultbir alongside imzaupdate() -> Result

Bu zaman iptal gerçekleşmelidir nasıl göstermek için üç modu vardır Guarddöner Successya Failed, aslında iptal etme arayan bağlıdır. Yani bir Selectorçağrı için Guard:

  1. İptal .self -> Sadece Guard(ve koşan çocuğunu) eğer çalışıyorsa ve koşulduysa iptal etFailed
  2. İptal .lower-> Yalnızca düşük öncelikli düğümleri çalışıyorlarsa ve koşul SuccessveyaRunning
  3. İptal .both -> Her ikisi de .selfve .lowerkoşullara ve çalışan düğümlere bağlı olarak. Çalışıyorsa kendini iptal etmek istiyorsan ve koşulu koşarsa ( bizim örneğimizde) kurala falsegöre düşük önceliğe sahip olduklarını düşünüyorsa, çalışan düğüme koşullandırmak ya da iptal etmek istersiniz . Başka bir deyişle, temelde her iki kavram da birleştirilmiştir.CompositeSelectorSuccess

Gibi Decoratorve aksine Compositesadece tek bir çocuk alır.

Her ne kadar Guardsadece pek gibi, sen iç içe olabilir tek çocuğu almak Sequences, Selectorsya da diğer tür Nodesdiğer dahil istediğiniz kadar Guardsveya Decorators.

Selector1 Guard.both[Sequence[EnemyNear?]] Sequence1 MoveToEnemy Attack Selector2 Sequence2 StandingOnGrass? Idle HumATune

Yukarıdaki senaryoda, ne zaman Selector1güncelleme olursa, her zaman çocuklarıyla ilişkili korumaların koşullarını kontrol eder. Yukarıdaki durumda Sequence1, Korumalı ve görevlere Selector1devam etmeden önce kontrol edilmesi gerekiyor running.

Ne zaman Selector2ya da Sequence1en kısa sürede çalıştıran EnemyNear?döndürür successbir sırasında Guards condition()daha sonra çek Selector1bir kesme yayınlayacak / için iptal running nodeve daha sonra her zamanki gibi devam edin.

Başka bir deyişle, davranışı, oturduğumuzdan çok daha reaktif kılan birkaç koşula dayanarak "boşta" veya "saldırı" dalına tepki verebiliriz. Parallel

Bu aynı zamanda tek korumak için izin verir Nodeçalışan karşı yüksek önceliğe sahip olduğunu Nodesaynı yerComposite

Selector1 Guard.both[Sequence[EnemyNear?]] Sequence1 MoveToEnemy Attack Selector2 Guard.both[StandingOnGrass?] Idle HumATune

Eğer HumATuneuzun sürüyorsa Node, Selector2olmasa da ilk önce bunu kontrol edecek Guard. Eğer NPC çim yaması üzerine ışınlanırsa, bir dahaki sefere Selector2koşar, koşmak için kontrol eder Guardve iptal HumATuneederIdle

O ışınlandın alırsa dışarı çim yama, Çalışıyorsa düğümü (iptal edecek Idle) ve taşımakHumATune

Burada gördüğünüz gibi, karar verme kendine Guarddeğil arayan kişiye güveniyor Guard. Kimin kuralları lower priorityaradığı ile kalır. Her iki örnekte de, Selectorneyin neyi oluşturduğunu tanımlar lower priority.

Eğer bir Compositeçağrınız Random Selectorolsaydı, o zaman belirli bir uygulamanın içindeki kuralları tanımlayacaktınız Composite.

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.