원거리 공격을 수행하는 Range EnemyAI를 구현해보았다.
무기는 활을 이용하여 공격하도록 만들었다.
💻 Range Service
Range Enemy의 비헤이비어 트리를 구성하기 앞서 BTService 를 상속받는 CBTService_Range 클래스를 생성하였다.
근거리 Enemy(Melee)와 달리 원거리 몬스터는 공격 범위가 아닌 회피 범위(Avoid Range)를 변수로 갖는다.
Service 클래스에서 주기적으로 호출되는 TickNode 함수에선 Avoid의 범위를 눈으로 파악할 수 있는 실린더 라인을 그리거나,
Enemy AI의 상태(aiState)를 변경하는 소스코드를 작성하였다.
Enemy가 Hitted 상태라면 SetHittedMode 상태로 설정하고,
블랙보드의 Target 객체가 존재하지 않는 경우엔 Wait Mode로 대기 상태에 빠지도록 설정하였다.
만약 Target이 존재한다면, Enemy가 해당 Target을 바라보도록 SetFocus 함수를 실행시켰다.
만약 Target이 Enemy의 회피 범위 안으로 들어오면, Enemy는 회피 모드(SetAvoidMode)로 설정되어 멀리 도망치게 된다.
(이때 도망가는 방법은 Warp 무기를 통해 EQS로 회피 지점을 구하는데 이에 대해선 다음 게시글에서 설명하였다.)
마지막엔 Target이 존재하지만, 회피 범위 밖에만 존재할 때 Action Mode를 호출하여 Target을 공격하도록 했다.
🏹 Enemy의 Bow 공격
원거리 Enemy는 활을 사용해 공격하기 때문에 기존에 플레이어가 사용할 용도로만 작성해놨던 SubAction_Aiming 클래스를 수정해주었다.
현재 프로젝트는 Aim 모드에서만 활을 발사하며 쏠 수 있도록 구현해놨기 때문에 CSubAction_Aiming 클래스를 수정한 것이다.
공격을 시작하는 Pressed 함수에서 Owner가 AIController를 가지고 있는지 아닌지를 판별한다.
플레이어는 PlayerController를 가지고, Enemy만 AIController를 갖기 때문에 해당 조건문을 통해 같은 무기를 사용하더라도, Owner가 플레이어인지, Enemy인지 판별할 수 있다.
만약 SubAction을 수행시킨 Owner가 Enemy라면 Aim모드에서 수행하는 카메라 줌인/아웃 기능을 실행시킬 필요 없기 때문에 return으로 함수를 탈출시켰다.
Released 함수에서도 마찬가지로 AIController의 유무를 판별하여 Enemy인 경우 함수를 탈출시켰다.
🎄 BT_Range
원거리 Enemy의 비헤이비어 트리도 새로 생성하고, Range용 블랙보드(BB_Range)도 새로 생성해주었다.
Equip 태스크를 Bow로 설정하여 검이 아닌 활을 장착하도록 하였다.
Weapon Component의 Data Asset에는 Bow를 추가하여 무기를 장착할 수 있도록 했다.
(Warp는 다음 게시글에서 장착 및 사용한다)
실행결과, Enemy_Range에게 가까이 다가가면 활을 장착하고, 공격하는 것을 볼 수 있었다.