Tôi đang cố gắng để có được đầu của mình xung quanh cây hành vi, vì vậy tôi đang bỏ qua một số mã kiểm tra. Một điều tôi đang vật lộn là làm thế nào để ưu tiên một nút hiện đang chạy khi có thứ gì đó có mức độ ưu tiên cao hơn xuất hiện.
Hãy xem xét cây hành vi đơn giản, hư cấu sau đây cho một người lính:
Giả sử rằng một số lượng bọ ve đã đi qua và không có kẻ thù nào ở gần, người lính đang đứng trên bãi cỏ, vì vậy nút Ngồi xuống được chọn để thực hiện:
Bây giờ hành động Ngồi xuống cần có thời gian để thực thi vì có một hình ảnh động để phát, do đó, nó trở lại Running
như trạng thái của nó. Một hoặc hai tích tắc trôi qua, hình ảnh động vẫn chạy, nhưng Kẻ thù gần? nút kích hoạt điều kiện. Bây giờ chúng ta cần ưu tiên nút Sit down ASAP để có thể thực thi nút Attack . Lý tưởng nhất là người lính thậm chí sẽ không ngồi xuống - thay vào đó anh ta có thể đảo ngược hướng hoạt hình của mình nếu anh ta chỉ bắt đầu ngồi. Để thêm phần chân thực, nếu anh ta vượt qua một số điểm bùng phát trong hoạt hình, thay vào đó chúng ta có thể chọn để anh ta ngồi xuống và sau đó đứng lại, hoặc có thể khiến anh ta vấp ngã để phản ứng với mối đe dọa.
Cố gắng hết mức có thể, tôi không thể tìm thấy hướng dẫn về cách xử lý tình huống này. Tất cả các tài liệu và video tôi đã tiêu thụ trong vài ngày qua (và nó đã được rất nhiều) dường như xoay quanh vấn đề này. Điều gần nhất mà tôi có thể tìm thấy là khái niệm đặt lại các nút đang chạy, nhưng điều đó không cho các nút như Ngồi xuống một cơ hội để nói "này, tôi chưa kết thúc!"
Tôi nghĩ có lẽ định nghĩa một Preempt()
hoặc Interrupt()
phương thức trên Node
lớp cơ sở của tôi . Các nút khác nhau có thể xử lý nó như thế nào họ thấy phù hợp, nhưng trong trường hợp này, chúng tôi sẽ cố gắng đưa người lính trở lại trên đôi chân của mình càng sớm càng tốt Success
. Tôi nghĩ rằng cách tiếp cận này cũng sẽ yêu cầu cơ sở của tôi Node
có khái niệm về các điều kiện riêng biệt với các hành động khác. Bằng cách đó, động cơ chỉ có thể kiểm tra các điều kiện và, nếu chúng vượt qua, hãy ưu tiên mọi nút hiện đang thực thi trước khi bắt đầu thực hiện các hành động. Nếu sự khác biệt này không được thiết lập, động cơ sẽ cần phải thực thi các nút một cách bừa bãi và do đó có thể kích hoạt một hành động mới trước khi ưu tiên chạy.
Để tham khảo, dưới đây là các lớp cơ sở hiện tại của tôi. Một lần nữa, đây là một đột biến, vì vậy tôi đã cố gắng giữ mọi thứ đơn giản nhất có thể và chỉ thêm sự phức tạp khi tôi cần, và khi tôi hiểu nó, đó là điều tôi đang đấu tranh ngay bây giờ.
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>
{
}
Có ai có cái nhìn sâu sắc nào có thể giúp tôi đi đúng hướng không? Là suy nghĩ của tôi theo đúng dòng, hoặc nó ngây thơ như tôi sợ?
Stop()
cuộc gọi lại trước khi thoát khỏi các nút hoạt động)