Unity/개발연습

[Unity] Behaviour Tree Editor 제작기 - 7

민트초밥 2024. 10. 21. 11:14

Sequence Node 로직 변경

 

Sequence Node의 문제점을 발견했다.

 

예를들어 아래와 같이 3초 대기 후 타겟에게 이동하는 상황에서 예상한 결과는 이렇지만

  1. 3초 대기

  2. 타겟과 근접할 때까지 이동

 

결과는 아래와 같았다.

  1. 3초 대기

  2. 타겟에게 이동하지만 1프레임만 이동

  3. 다시 3초 대기 후 1프레임 이동

 

 

 

 

 

문제는 Wait 노드의 구현 방식이었다.

 

일정 시간이 지난 후 elapsedTime 변수를 0으로 만들고 Success 상태로 변경하기 때문에 다음 평가 때 Running 상태가 되면서 Wait 노드를 재실행한다.

 

public override NodeStates Evaluate()
{
    if (elapsedTime < waitTime)
    {
        elapsedTime += Time.deltaTime;
        return NodeStates.Running;
    }
    else
    {
        elapsedTime = 0f;
        return NodeStates.Success;
    }
}

 

 

 

 

즉, Action Node는 자체에서 Success 상태를 변경시키지 않아야 한다.

 

 

Wait 노드에서 초기화를 시킬 수 있는 함수 추가

 

public override void Refresh()
{
    base.Refresh();
    elapsedTime = 0f;
}


public override NodeStates Evaluate()
{
    if (elapsedTime < waitTime)
    {
        elapsedTime += Time.deltaTime;
        return NodeStates.Running;
    }
    else
    {
        return NodeStates.Success;
    }
}

 

 

 

 

Sequence 노드에 모든 자식 노드들이 Success인 경우 초기화 함수 실행

 

public override NodeStates Evaluate()
{
    foreach (string nodeGuid in childNodeGuidList)
    {
        BehaviourNode node = tree.FindNode(nodeGuid);

        if (node == null)
        {
            Debug.LogError($"{nameof(SelectorNode)} : Child Node Not Found");
            continue;
        }

        switch (node.Evaluate())
        {
            case NodeStates.Running:
                NodeState = NodeStates.Running;
                return NodeState;

            case NodeStates.Failure:
                NodeState = NodeStates.Failure;
                return NodeState;
        }
    }

    // 모든 자식 노드들이 Success 상태인 경우 None 상태로 변경
    foreach (string nodeGuid in childNodeGuidList)
    {
        BehaviourNode node = tree.FindNode(nodeGuid);

        if (node is ActionNode actionNode)
            node.Refresh();
    }

    NodeState = NodeStates.Success;
    return NodeState;
}

 

반응형