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:
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 :
Şimdi Otur aşağı eyleminin yürütülmesi zaman alıyor çünkü oynatılacak bir animasyon var, bu yüzden Running
durumu 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 Node
sı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 Node
diğ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ı?
Stop()
aktif düğümleri çıkmadan önce geri arama)