Дерево поведения: как / когда вернуть «запущенное» состояние на конечных узлах? - PullRequest
0 голосов
/ 20 сентября 2019

Я реализовал простой алгоритм Дерева Поведения, который я намерен использовать внутри проекта Unity.В основном это работает, как я и ожидал, за исключением того, что у меня возникают проблемы с его правильным использованием, что может быть вызвано каким-то моим недопониманием.Моя проблема заключается в следующем:

Если конечному узлу требуется много времени, чтобы завершить, например, действие, которое заставляет игровой блок следовать определенному пути, это означает, что конечный узел в данный момент находится в «работающем»государство.Однако, если я верну состояние, я больше не смогу запустить оставшуюся функцию, что означает, что я не могу добраться до пункта назначения.

Так что мой вопрос: как правильно сказать моему дереву, чтолистовой узел работает?

Вот что я получил в своем классе ActionNode:

public class ActionNode : BTNode
{
    public delegate NodeStates ActionNodeDelegate();
    protected ActionNodeDelegate nodeAction;

    public ActionNode(ActionNodeDelegate action)
    {
        nodeAction = action;
    }
    public override NodeStates Evaluate()
    {
        switch (nodeAction())
        {
            case NodeStates.FAILURE:
                currentNodeState = NodeStates.FAILURE;
                return currentNodeState;
            case NodeStates.SUCESS:
                currentNodeState = NodeStates.SUCESS;
                return currentNodeState;
            case NodeStates.RUNNING:
                currentNodeState = NodeStates.RUNNING;
                return currentNodeState;
            default:
                currentNodeState = NodeStates.FAILURE;
                return currentNodeState;
        }
    }
}

Если вам нужно проверить другие классы, все это основано на этой статье .Связывая его ради сохранения чистоты потока.

Что касается примера действия, рассмотрите это:

private NodeStates FollowPath() {        
    bool targetReached;
    if (targetReachable)
        targetReached = WalkToTarget();
    if (targetReached)
        return NodeStates.SUCESS;
    else
        return NodeStates.FAILURE;
}

Что мне интересно, если WalkToTarget занимает много времени, какя возвращаю "рабочее" состояние?

Я прочитал много разных статей на эту тему, но я не могу понять точную концепцию этих состояний.Я понимаю, как, например, сказать, что узел Sequence или Selector запущен.

Единственная мысль, которая пришла мне в голову, - сохранить оставшийся путь внутри переменной в классе моего врага и вызватьметод каждый тик обновляет игру, но я чувствую, что это просто плохое кодирование.

Должны ли листовые узлы возвращать "работающие" в любой момент?Если да, то в каких случаях это произойдет?Любые примеры будут оценены!

1 Ответ

0 голосов
/ 24 сентября 2019

Хорошо, я понял, что я делаю не так.Я предполагал, что мое дерево отвечало за выполнение кода действия, когда на самом деле предполагается, что он оценивает только состояние каждого узла.В этом случае мой приведенный выше пример изменится на что-то вроде этого:

private NodeStates ShouldFollowPath() {        
    if (targetReachable && this.position != target.position)
        return NodeStates.RUNNING;
    else if (this.position == target.position)
        return NodeStates.SUCESS;
    else
        return NodeStates.FAILURE;
}

И затем я проверим состояние вышеупомянутого узла после оценки дерева и выполню мой код FollowPath:

private ActionNode FollowPathNode = new ActioNode(ShouldFollowPath);

private void Update()
{
    FollowPathNode.evaluate();
    if (FollowPathNode.nodeState == NodeStates.RUNNING)
        FollowPath();
}

Итак, я неправильно понял использование дерева поведения.Приведенный выше пример решает мои проблемы.

...