Saya mencoba untuk mendapatkan kepalaku sekitar pohon perilaku, jadi saya mengeluarkan beberapa kode tes. Satu hal yang saya perjuangkan adalah bagaimana mendahului simpul yang sedang berjalan saat sesuatu dengan prioritas yang lebih tinggi muncul.
Pertimbangkan pohon perilaku fiktif sederhana berikut untuk seorang prajurit:
Misalkan sejumlah kutu telah lewat dan tidak ada musuh di dekatnya, prajurit itu berdiri di atas rumput, sehingga simpul Duduk dipilih untuk eksekusi:
Sekarang aksi Duduk butuh waktu untuk mengeksekusi karena ada animasi untuk dimainkan, sehingga kembali Running
sebagai statusnya. Satu atau dua tanda centang lewat, animasi masih berjalan, tetapi Musuh dekat? pemicu node kondisi. Sekarang kita perlu mendahului node Sit ASAP sehingga kita dapat menjalankan node Attack . Idealnya prajurit itu bahkan tidak akan selesai duduk - dia malah bisa membalikkan arah animasinya jika dia baru saja mulai duduk. Sebagai tambahan realisme, jika dia melewati titik kritis dalam animasi, kita mungkin memilih untuk membiarkannya selesai duduk dan kemudian berdiri lagi, atau mungkin membuatnya tersandung dalam tergesa-gesa untuk bereaksi terhadap ancaman.
Berusaha sekuat tenaga, saya belum dapat menemukan panduan tentang bagaimana menangani situasi semacam ini. Semua literatur dan video yang saya konsumsi selama beberapa hari terakhir (dan itu sudah banyak) tampaknya mengesampingkan masalah ini. Hal terdekat yang dapat saya temukan adalah konsep mengatur ulang node yang sedang berjalan, tetapi itu tidak memberikan node seperti Duduklah kesempatan untuk mengatakan "hei, saya belum selesai!"
Saya berpikir mungkin mendefinisikan Preempt()
atau Interrupt()
metode pada Node
kelas dasar saya . Node yang berbeda dapat mengatasinya sesuai keinginan mereka, tetapi dalam kasus ini kami akan berusaha mendapatkan prajurit itu kembali secepatnya dan kemudian kembali Success
. Saya pikir pendekatan ini juga akan mengharuskan basis saya Node
memiliki konsep kondisi secara terpisah untuk tindakan lain. Dengan begitu, mesin hanya dapat memeriksa kondisi dan, jika mereka lulus, mendahului setiap node yang sedang mengeksekusi sebelum memulai eksekusi tindakan. Jika diferensiasi ini tidak ditetapkan, mesin akan perlu mengeksekusi node secara membabi buta dan karena itu dapat memicu tindakan baru sebelum mencegah yang sedang berjalan.
Untuk referensi, di bawah ini adalah kelas dasar saya saat ini. Sekali lagi, ini adalah lonjakan, jadi saya telah berusaha untuk menjaga hal-hal sesederhana mungkin dan hanya menambah kompleksitas ketika saya membutuhkannya, dan ketika saya memahaminya, itulah yang sedang saya perjuangkan sekarang.
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>
{
}
Adakah yang punya wawasan yang bisa mengarahkan saya ke arah yang benar? Apakah pemikiran saya sesuai dengan garis yang benar, atau naif seperti yang saya takutkan?
Stop()
panggilan balik sebelum keluar dari node aktif)