행동 트리로 공격

이득우의 Unreal C++ 게임 개발 표준

Behavior Tree의 Tracking Branch에서 공격 기능을 추가하기 위한 Selector와 Sequence를 추가하고 다음과 같이 수정합니다.


이번에는 보드 데코레이터를 사용하는 대신 플레이어가 공격 범위에 있는지 감지하는 데코레이터를 만들어 보겠습니다.


이제 새 클래스를 만들었으므로 CoreMinimal.h를 ArenaBattle.h로 변경합니다.


Decorator 클래스는 CalculateRawConditionValue() 함수를 실행하여 조건을 확인합니다.

  • 이 함수는 클래스의 멤버 변수 값을 변경할 수 없도록 const로 선언되어 있습니다.


필요한 헤더를 추가합니다.


생성자에서 데코레이터 이름을 설정합니다.


행동 트리를 실행하는 제어 폰과 테이블 키에 저장된 플레이어의 목표 사이의 거리가 200 미만인지 확인합니다.

  • AActor::GetDistanceTo(AActor) 함수를 사용하여 액터 사이의 거리를 계산할 수 있습니다.


데코레이터를 추가하여 플레이어를 공격하거나 두 하위 노드를 추적합니다.

  • 오른쪽의 데코레이터는 반대 조건을 확인하고 false인 경우 분기합니다.



플레이어를 공격할 새 작업을 만듭니다.


CoreMinimal.h를 ArenaBattle.h로 변경합니다.


공격 작업은 공격 애니메이션이 끝날 때까지 기다려야 합니다.

따라서 InProgress가 반환되고 공격이 끝나면 FinishLatentTask() 함수를 호출하여 작업을 종료해야 합니다.

  • 이 함수에 의해 종료되지 않으면 현재 작업에 남아 있습니다.

Tick ​​함수를 활성화하고 IsAttacking 값이 false가 되면 FinishLatentTask() 함수로 작업을 종료합니다.


생성자에서 작업의 틱 기능을 활성화하고 IsAttacking 변수의 기본값을 설정합니다.

  • bNotifyTick의 값이 참이면 TickTask() 함수가 모든 틱에서 실행됩니다.


나머지 함수를 작성하기 전에 외부에서 Attack() 함수를 실행하고 공격이 끝나면 작업에 알릴 수 있도록 문자 클래스로 전환해야 합니다.

캐릭터의 Attack() 함수를 public으로 변경하고 OnAttackEnd 델리게이트가 공격 종료 시 발동하도록 선언합니다.

OnAttackEnd 델리게이트에 등록된 함수를 실행하는 애님 인스턴스의 OnMontageEnded 델리게이트에 등록된 OnAttackMontageEnded() 함수에 부분을 추가합니다.


공격 작업으로 돌아가 헤더를 추가합니다.


Attack 태스크가 실행되면 캐릭터 클래스의 Attack() 함수를 실행하고 IsAttacking 변수를 true로 설정합니다.

공격이 완료되기 전에 작업이 완료되면 안 되므로 InProgress를 반환하고 공격이 완료되면 IsAttacking 변수를 false로 설정합니다.


IsAttacking의 값이 false가 될 때까지 기다렸다가 공격이 종료되어 true가 되면 FinishLatentTask() 함수를 실행하여 작업을 종료합니다.


액션 트리에 공격 태스크를 추가합니다.


문제는 AI가 플레이어를 공격하는데, 시작한 방향으로만 계속해서 공격한다는 점이다.


공격 중에 플레이어를 향하도록 AI를 리디렉션하는 새 작업을 만듭니다.


CoreMinimal.h를 ArenaBattle.h로 변경합니다.


생성자와 ExecuteEvent() 함수 재정의를 선언합니다.


헤더 추가


생성자에서 작업 이름을 변경합니다.


LookVector는 현재 AI가 플레이어를 바라보는 방향입니다.

  • Z축은 0으로 설정되고 XY 평면에 투영됩니다.

AI의 정방향을 LookVector와 정렬하고 싶기 때문에 MakeFromX() 함수를 사용합니다.

  • MakeFrom(X, Y, Z) 함수는 정규화된 벡터를 전달할 필요가 없습니다.

FMath::RInterpTo() 함수는 현재 회전 값에서 플레이어를 향하는 방향으로 2 DeltaTime의 속도로 회전할 때 회전 값을 가져오는 데 사용됩니다.

  • 이 함수는 Run & Forget 메서드에서 타이머나 쓰레드를 실행하고 자신을 반환하는 함수가 아닙니다.
  • 현재 Turn 작업은 계속 실행되지만 Attack 작업은 나중에 Simple Parallel Composite를 통해 실행됩니다.
  • 이 함수는 시작과 끝이 간단하므로 일정한 속도로 회전하려면 FMath::RInterpConstantTo() 함수를 사용합니다.


기존 시퀀스를 Simple Parallel Composite로 바꿉니다.

  • 왼쪽의 보라색과 관련된 메인 작업이 실행되는 동안 검은색과 관련된 하단 노드가 백그라운드에서 실행됩니다.
  • Main Task에서는 Task만 Verbatim으로 실행할 수 있지만 오른쪽에 다른 Composite를 등록할 수 있습니다.
  • 오른쪽 자식 노드는 하나의 분기만 가질 수 있습니다.


작업과 데코레이터를 만들고 동작 트리를 사용하여 공격 기능을 구현했습니다.