Sputnik(4) - Enemy

JUSTICE_DER·2023년 10월 6일
0

🛰Sputnik (Satellite)

목록 보기
7/9

적, 타격, 피격을 구현해보려고 한다.

1. 적 (간단)

  • 우선 기본 적 / 보스 총 2가지 종류로 만들려고 한다.

1-1. 적 생성

1 우선 Enemy를 표현할 Character 액터를 CPP로 추가하고,
BP로 상속받아 생성한다.

BP를 통해 시각적으로 보며,
SkeletalMesh를 회전하고 높이를 맞춰놓을 수 있기 때문이다.

2 해당 Character를 움직일 AIController를 CPP로 추가하고,
BP로 상속받아 생성한다.

Controller를 굳이 BP로도 설정하는 이유는,
다음 단계에서 볼 수 있다.
간단하게 변수의 값을 시각적으로 설정가능.
혹시 모를 BP노드의 사용 + 일관성 을 위해서도 있다.

3 BT와 BB를 생성하여 서로 연결하고,
BT를 AIController와 연결한다.

AIController CPP클래스에 위처럼 설정하고 BP에서 BT를 매핑

이로써 AIController와 BT, BB를 연결했다.

1-2. BT 설정

1 BT에서 사용할 BB변수값들을 AIController에서 설정한다.

NavMesh 설정을 진행했다. (P로 확인)

2 BT Task노드나 BT Service노드를 생성한다.

  • Task는 사용자 단위 행동을 정의하기 위해 사용하는 것이고,
  • Service는 주기적으로 정보를 저장하거나 제공하는 역할로,
    조건을 만족하는지 확인할 때 사용된다.

지금은 Service Node만 우선 만들어본다.
플레이어가 감지되면, 플레이어의 위치로 따라가도록 하기 위해서.

  • Service

간단하게 이런식으로 작성을 해보았다.
플레이어를 확인하면 SetFocus로 플레이어를 쳐다보며 따라오게 될 것이다.
반대로 감지되지 않는다면, ClearFocus로 원래 자리를 쳐다보며 돌아가게 된다.

하지만, ServiceNode의 TickNode에 들어가서
interval이 0.2마다 실행되어 일반 Tick에 비해 상당히 부자연스럽다.
그래서 0.01인 clamp 최소값으로 지정해보았는데,
왜인지 적의 속도가 10배정도 느려지게 된다.

  • 왜일까?
    문제는 On Value Change에서 On Result Change로 바꾸니 해결.

문제를 해결하고 BT를 간단히 위처럼 구성해 보았다.

123 구역으로 나눠서 볼 때,

  • 1은 Detect에 의해
    PlayerLocation과 ChasedTarget가 감지된다면, 실행되는 부분
    PlayerLocation으로 이동하고, Service노드에 의해 ChasedTarget을 보며 이동.
    (사실 Service노드가 없어도 Location을 따라갈 때, 보게 되어있다)
    (그리고 ChasedTarget을 BB에서 Actor로 바꿔야만 노드에 적용할 수 있다)

  • 2는 플레이어를 놓친 경우로,
    마지막으로 감지된 LastPlayerLocation으로 한 번 더 이동해 본다.
    이동하고, LastPlayerLocation을 초기화한다.

  • 3은 플레이어를 완전히 놓친 경우로,
    원래 위치로 이동 및 원래 방향으로 회전한다.

1-3. Anim 설정

  • 상관관계파악 후,
    AnimInstance에는 Anim을 실행할 트리거만,
    Enemy BP는 방향전환, 속도, 트리거의 수정만 넣기

Enemy BP에서 구현하고 싶은 기능은 회전과 더불어

  • 탐색하는 경우,
    • 플레이어의 방향을 향하기
    • 걷는 애니메이션
  • 탐색을 잠시 멈추고 돌아가는 경우,
    • Idle 애니메이션
    • 돌아갈 때는 다시 걷는 애니메이션
  • 탐색을 중지한 경우,
    • Idle 애니메이션

여기서 가장 까다로운 부분은,
탐색을 멈추고 돌아가는 경우일 것이다.

언제 걷기를 실행하고, 언제 Idle을 실행할지
그 값을 어떤 변수로 설정하는 것이 자연스러울지 생각해본다.

  • 회전은 BP에 구현하였는데,,

위의 노드가 핵심이다. 위의 노드로 봐야하는 Rotator를 구하고,
해당 값의 z만을 Pawn의 Rotator에 적용하였다.

AI의 회전이 이상했다 - 아래의 글로 해결

https://forums.unrealengine.com/t/strange-ai-movement/2725

  • 탐색 관련해서 2가지의 BlackBoard 변수가 핵심이다.
    ChasedTarget / ChaseFlag
  • 실제로 탐지 범위에 있다면, ChasedTarget을 설정하고,
    해당 ChasedTarget이 존재한다면,
    해당 오브젝트의 위치를 BlackBoard에 계속 갱신하며 따라가게 한다.
  • ChaseFlag는 탐지중인지 아닌지를 설정하는 변수로 두었고,
    ChasedTarget과 갱신 주기가 살짝 다르다.
    탐색 범위 내에 없어도 = ChasedTarget이 없어도
    마지막으로 발견된 위치까지 가야하기 때문에,
    ChaseFlag는 탐색이 시작될 때부터 이때까지 true로 둔다.
    그리고 멈춘 시점에 false로 갱신하고, 다시 true로 갱신하여 이동시킨다.
  • AnimInstance는 이 ChaseFlag에 맞춰서 걷는 모션을 실행한다.
  • BT는 다음과 같이 구성된다.
  • Detect 서비스 노드를 통해, 구체 반경을 감지하고,
    ChasedTarget을 설정하고,
    ChasedTarget의 PlayerLocation, LastPlayerLocation을 갱신한다.
  • 1

    PlayerLocation으로 이동한다.
    Sequence는 공격을 위해서 일단 공백으로 두었다.
  • 2

    Detect에 의해 감지되는 것이 없다면, PlayerLocation은 갱신되지 않는다.
    LastPlayerLocation은 가장 최근의 PlayerLocation을 담고 있고,
    LastPlayerLocation으로 이동한다.
    즉 플레이어가 있는지 한 번 더 확인하는 목적의 코드이다
    이동하고, LastPlayerLocation의 값을 해제하고,
    ChaseFlag의 값을 해제-기다림-ChaseFlag의 값을 다시 설정 한다.
    그 이유는, AnimInstance 떄문.
  • 3

    ChaseFlag값이 있다면 = 어딘가로 이동하는 상태라면
    원래 Location으로 이동하고,
    TurnBack으로 원래 Rotation으로 돌리고,
    ChaseFlag을 false로 둔다.
profile
Time Waits for No One

0개의 댓글