본문 바로가기
Unreal 게임 개발/Unreal Tool 활용

Unreal BehaviorTree OnBecomeRelevant & OnCeaseRelevant

by daisy0461 2024. 9. 24.

OnBecomeRelevant & OnCeaseRelevant

먼저 OnBecomeRelevant를 도큐먼트에 검색해보면 두가지가 나온다.

  1. https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/AIModule/BehaviorTree/Decorators/UBTDecorator_BlueprintBase/OnBecomeRelevant?application_version=5.4
  2. https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Developer/AITestSuite/BehaviorTree/UTestBTDecorator_Blackboard/OnBecomeRelevant?application_version=5.4

1번은 UBTDecorator_BlueprintBase이고 2번은 UBTDecorator_BlackboardBase에 있는 것이다.

일단 이 글은 C++에서 어떻게 사용하는지 관련해서 작성할 것이기에 1번은 제외한다.

제외하는 이유는 

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/AIModule/BehaviorTree/Decorators/UBTDecorator_BlueprintBase?application_version=5.0

해당 도큐먼트에 이렇게 강조되어 있기 때문이다.

이후에 동일하게 OnCeaseRelevant도 두가지가 있지만 UBTDecorator_BlackboardBase만 다룬다.

해당 도큐먼트 링크는 다음과 같다.

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/AIModule/BehaviorTree/Decorators/UBTDecorator_BlackboardBase/OnCeaseRelevant?application_version=5.2

 

해당 도큐먼트 들어가면 솔직히 별 내용이 없다.

OnBecomeRelevant : 실행흐름이 활성화될 때 Call된다.

OnCeaseRelevant: 실행흐름이 비활성화될 때 Call된다.

 

진짜 이게 끝이다. 글만 봐서는 잘 모르겠으니 한번 실제 적용한 동영상을 보면 이해가 될듯 하다.

void UBTD_IsWithInIdealRange::OnBecomeRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	// Decorator가 활성화될 때 호출
	Super::OnBecomeRelevant(OwnerComp, NodeMemory);
    bNotifyTick = true; TickFlag = false;
    UE_LOG(LogTemp, Display, TEXT("OnBecomeRelevant Call"));
}

void UBTD_IsWithInIdealRange::OnCeaseRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	// Decorator가 비활성화될 때 호출
	Super::OnCeaseRelevant(OwnerComp, NodeMemory);
    bNotifyTick = false; TickFlag = true;
    UE_LOG(LogTemp, Display, TEXT("OnCeaseRelevant Call"));
}

void UBTD_IsWithInIdealRange::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
    bool bConditionValue = CalculateRawConditionValue(OwnerComp, NodeMemory);

    if (bConditionValue != LastConditionValue) {
        OwnerComp.RequestExecution(this);
    }

    LastConditionValue = bConditionValue;
    if(!TickFlag){
        UE_LOG(LogTemp, Display, TEXT("Tick Node!!"));
        TickFlag = true;
    }
}

코드는 이런식으로 만들었다.

 

그럼 실행시켜보면

처음에 OnBecomeRelevant가 Log에 출력된다.
그렇다면 BehaviorTree의 우측(낮은 우선순위) Strafe를 할때 활성화가 되는 것이다.

그리고 다시 자기 자신을 체크하면 OnCeaseRelevant가 출력된다.

 

그러면 여기서 알 수 있는 사실이 있다.

'실행흐름이 활성화 or 비활성화 될 때 Call이 된다'의 의미는 다음과 같이 더 직관적으로 설명이 가능하다.

OnBecomeRelevant : 자신보다 하위노드가 실행될 때 Call된다.

OnCeaseRelevant: 자신을 포함한 자신보다 우선순위 노드가 실행될 때 Call된다.

 

 

이것을 활용해서 위 코드에서는 Tick이 사용되지 않아도 되는 부분에선 Tick을 비활성화 한다.

 

주의사항

UBTD_IsWithInIdealRange::UBTD_IsWithInIdealRange()
{
    bNotifyBecomeRelevant = true;
	bNotifyCeaseRelevant = true;
}

생성자에서 다음과 같이 활성화 시켜야 제대로 호출이 된다.