🤖 Behavior Tree를 사용해서 직접 AI를 구현해보자.
이번 포스팅에는 무기 장착, 해제 애니메이션 추가와 Enum을 사용한 상태구분으로 BT를 깔끔하게 정리해보겠습니다.
설명의 편의를 위해서
행동트리 (Behavior Tree)는 앞으로 BT로,
블랙보드 (Black Board)는 앞으로 BB로,
AI Controller는 AIC라고 부를 예정입니다.
Ali Elzoheiry님의 Smart AI 강의 영상을 보면서 공부하였습니다.
시리즈의 양이 많지만 정리가 아주 잘 되어 있으니 한번씩 시청을 추천드립니다.
저는 Mixamo에서 칼을 꺼내는 애니메이션 하나를 가져왔습니다.
1개만 가져와도 반전하면 되니까 그대로 쓰겠습니다!
칼을 차는 애니메이션을 준비하셨으면 Create AnimMontage로 애니메이션 몽타쥬를 생성해주세요.
아래 단계를 해주세요.
Notify는 우클릭을 하시고 Montage Notify를 추가해주시면 됩니다.
AM_UEQ_Sword에 들어 오시면 먼저 애니메이션을 반전해주겠습니다.
플레이되는 애니메이션을 선택하고 Details의 Play Rate를 -1로 해주세요.
그 후 AM_UEQ_Sword도 동일하게 작업해주세요.
이것으로 애니메이션이 모두 준비되었습니다.
BP_Enemy의 Event Graph로 이동해주세요.
그리고 무기 장착 여부를 판단하는 isEquipSword 변수를 public으로 생성해주세요.
애니메이션 종료 파악을 위한 dispatchers를 추가해주겠습니다.
장착, 해제 각각 1개씩 생생해주세요.
그리고 이전에 생성했던 Equip Sword를 수정할 겁니다.
근데 혹시 몰라 처음부터 진행해주겠습니다.
커스텀 이벤트 생성해시고, Is Equip Sword를 True로 설정하도록 연결해주세요.
Play Montage 노드를 추가해주세요.
Skeletal Mesh는 노드를 추가해주시고, AM_EQ_Sword를 선택해서 넣어주세요.
다른 값들은 그대로 두셔도 됩니다.
Notify Name을 끌어서 Switch on Name을 추가해주세요.
그리고 노드를 선택 후 Details를 보겠습니다.
Has Default Pin을 체크 해제 해주세요.
그리고 Pin을 하나 추가해주세요.
이름은 몽타쥬에서 설정했던 Notify의 이름을 그대로 넣으셔야 합니다.
SpawnActor 노드를 추가해주세요.
그리고 Class를 만들었던 BP_Sword로 넣으면 해당 클래스에 맞게 이름이 변경됩니다.
그리고 Spawn Transform은 Get Actor Transform을 Self로 해서 넣어주겠습니다.
Return Value를 우클릭해서 Promote to Variable을 해주세요.
바로 해당 액터에 대한 변수가 생성됩니다.
SwordActor라고 지어 주겠습니다.
이제 캐릭터에게 부착해주겠습니다.
생성했던 OnEquipEnd의 Dispatcher를 Call로 추가해주세요.
그리고 On Completed와 On Interrupted를 이어 주세요.
여기까지가 무기 장착 커스텀 이벤트였습니다.
❗컴파일 저장❗해주세요.
비슷합니다.
빠르게 진행하겠습니다.
is Equip Sword를 false로 set해주시고,
Play Montage를 AM_UEQ_Sword로 넣어 주세요.
그리고 여기서는 Call On Unequip End를 On Completed와 On Interrupted를 이어 주세요.
Switch on Name을 아까와 동일하게 설정해주세요.
이번엔 이름이 UnequipSword로 해주어야 합니다.
그리고 아까 생성한 Sword Actor를 사용해서 Destroy Actor 해주세요.
이걸로 모든 애니메이션 재생 준비가 완료되었습니다.
❗컴파일 저장❗해주세요.
기존의 태스크를 수정하겠습니다.
이전에 공격 애니메이션 태스크의 실행 종료를 했던 방식과 동일하게 해주세요.
BTT_UnequipSword로 태스크를 생성해주세요.
장착 태스크의 로직과 동일합니다.
다만 중간에 호출하는 커스텀이벤트가 UnequipSword라는 것만 다르죠.
❗컴파일 저장❗해주세요.
AI 각 상태를 저장할 Enum을 생성 해주겠습니다.
일단 생각나는 상태들을 추가해봤습니다.
그리고 BB로 이동해서 State를 Enum으로 키 생성해주세요.
그리고 Details에서 E AIState로 설정해주세요.
임시로 다른 연결을 끊어 주겠습니다.
추적, 공격과 패트롤에 대한 Selector를 만들어주세요.
그리고 우클릭해서 BB를 데코레이터로 넣어 주세요.
그리고 데코레이터를 클릭하고 Blackboard Key를 State로 해주세요.
그럼 Key Query와 Key Value가 생깁니다.
Is Equal To 같을 때를 의미하죠?
각각 Attacking과 Passive를 넣어주세요.
간단한 조건문과 동일한 동작입니다.
기존의 무기장착을 Sequence로 따로 빼주겠습니다.
PassiveState Selector 하위에 Selector를 추가해주세요.
이건 무기 장착 해제와 상태를 구분하는 역할을 할 겁니다.
그리고 무기 장착 해제 태스크를 이어주고, IsEquipSword 데코레이터를 넣어 주세요.
Selector를 하나 더 만들어서
Partol Route가 있다면 패트롤을,
그렇지 않다면 Idle상태로 있도록 만들어 주겠습니다.
전체 사진은 아래와 같습니다.
저장해주세요.
일단은 Passive와 Attacking으로 설정해주는 함수 2개만 만들겠습니다.
AIC_Enemy에서 각 State를 설정해주는 함수를 만들겠습니다.
SetStateAs의 이름으로 Passive와 Attacking을 만들어 주겠습니다.
Attacking은 한가지 작업이 추가됩니다.
AttackTarget을 지정해주는 것이죠.
Input을 AttackTarget으로 Actor타입으로 넣어주세요.
그리고 Object 레퍼런스로 해주세요.
그리고 Set Value as Object를 넣어서 대상을 넣어줍시다.
그리고 Passive와 동일하게 노드를 이어주시고,
Enum값만 Attacking으로 해주세요.
Event Graph의 Event On Possess를 수정해주겠습니다.
Run Behavior Tree노드를 제외하고 모두 날려주세요.
그리고 Set State as Passive 함수 노드만 추가해주세요.
BP_Player의 Event Graph로 가주세요.
임시로 키를 눌러서 스테이트를 변경해주겠습니다.
저는 1번 키로 하겠습니다.
Get Actor of Class를 가져와주세요.
Actor Class는 BP_Enemy로 해주세요.
그리고 Get AIController를 가져옵니다.
이어서 AIC_Enemy를 Cast해주세요.
그리고 Flip Flop을 만들어줍시다.
이어서 Cast된 AIC_Enemy노드에서 만들었던 Set State as 함수 2개를 가져와주세요.
A는 Attacking, B는 Passive에 이어주세요.
Attacking은 Self를 AttackTarget으로 넣어주세요.
전체 블루프린트입니다.
❗컴파일 저장❗해주세요.
자 이제 실행해서 애니메이션이 잘나오는지 확인해보겠습니다.
1번을 눌러서 확인해봅시다.
애니메이션 변환이 성공적입니다!
그런데 한가지 문제가 있습니다.
바로 State가 바로바로 전환되지 않는다는 것입니다.
이는 현재 실행중인 Behavior Tree의 시퀀스가 종료된 후에 그 다음 시퀀스로 넘어가기 때문입니다.
그래서 우리는 바로 다음 시퀀스로 넘어가도록 수정해주어야 합니다.
State를 전환하는 각각의 Decorator가 있죠?
선택해서 Details의 Observer Aborts를 Self로 변경해주세요.
다시 테스트 해보면 바로바로 폼이 전환되는 것을 확인할 수 있습니다!
이것으로 애니메이션 전환과 Notify를 사용해서 무기가 장착, 해제되는 효과를 주는데 성공했습니다.
그런데 마지막 테스트를 보면 AI가 무기를 꺼내면서 슬라이딩을 하고 있습니다.
해당 이슈에 대한 수정과 추가적인 기능은 다음 포스팅에 진행하겠습니다.
감사합니다.