3D Action RPG (4) - Enemy FSM

mingu Lee·2025년 6월 19일

Unity3D - 3D Action RPG

목록 보기
4/5
post-thumbnail

간단 요약


Enemy의 Idle, Chasing, Attack, Hit, Die State를 구현.
Chasing State에서는 NavMeshAgent를 사용하여 Player를 추적하도록 설정.
Player도 Enemy와 마찬가지로 Hit, Die 등 남는 State 구현.
Player와 Enemy의 상호작용으로 인한 State 전환 시 발생하는 버그 수정.

구현 과정


  1. Idle State
  2. Chasing State
  3. Attack State
  4. Hit State
  5. Die State

Idle State


Idle State는 가만히 있다가 주변 탐색 범위에 Player가 존재할 경우 Chasing State로 전환.

Chasing State


Chasing State는 Player를 추적하는 State이며, NavMeshAgent를 사용함.

NavMeshAgent를 통해 Player를 추적하여 Vector를 계산하고, 실제 이동은 Character Controller를 사용하여 움직임.

Player를 바라보면서 추적할 경우 이동 방향과 회전 방향이 다르므로, Player를 추적하는 중에는 NavMeshAgent를 통해 계산한 desiredVelocity를 참조하여 방향을 결정.

맵으로 사용한 바닥, 계단 등의 구조물은 하나의 Group으로 묶어서 부모 Object에 NavMesh Surface Component를 추가하여 Bake 함.

Attack State


Chasing State에서 Attack Range 이내에 Player가 존재할 경우 Attack State로 전환.

Player와 마찬가지로 무기에 Collider Object를 추가하여 Attack Animation의 특정 프레임에서 Collider가 활성화되도록 함.

Attack 중에는 Player를 계속 바라보도록 설정.

만약 Attack이 끝났을 때 Player가 계속 범위 내에 있으면 다시 Attack State, 없으면 Chasing State로 전환.

Hit State


Player에게 공격 당하면 전환되는 State.

Player의 Weapon Collider에 충돌할 경우 Health가 감소하며, OnTakeDamage Event가 발생하도록 설정.

이 Event를 StateMachine에서 확인하여 Hit State로 전환.

Hit State로 전환 시 피격 Animation이 재생되며, 일정 시간 뒤에 다시 Idle State로 전환.

Player도 Enemy와 마찬가지로 Hit State 구현.

Die State


Health가 0이 되면 전환되는 State.

Hit과 마찬가지로 Health가 0이 될 경우 OnDie Event가 발생하고, StateMachine에서 이를 확인하여 Die State로 전환 됨.

Die State로 전환 시 Die Animation이 재생되고, 죽을 경우 Target Component를 제거하여 Target으로 설정할 수 없도록 함.

Player도 Enemy와 마찬가지로 Health가 0이 될 경우 Die State로 전환 됨.

Enemy 사망 Player 사망

구현 중 발생한 문제 및 해결방안


  • 각 State 자체만 놓고 보면 별다른 버그가 발생하지 않았지만, Player와 Enemy가 서로 공격을 주고 받으며 빠르게 State 전환과 Animator 변경이 발생할 때 State와 Animator가 불일치하는 버그가 발생함.
    특히 Enemy와 Player가 서로 동시에 공격을 주고 받을 때가 문제였는데, 내가 작성한 로직에서는 Player의 공격 Animation에 Event를 추가하여 Weapon Collider를 활성화 및 비활성화 하는 방식이었음.
    이때 Player든 Enemy든 공격하는 도중에 상대방으로 부터 공격을 받아 Hit State로 전환되면 Attack State의 Exit에서 바로 Weapon Collider를 비활성화 하지만, Animation이 Blend 되는 과정에서 Exit이 실행되어 Collider가 비활성화 됐다가 Attack Animation으로 인해 다시 활성화되고 Hit State로 전환되는 현상이 발생.
    이를 해결하기 위해 Weapon Collider를 활성화하는 함수에 조건을 추가하여 현재 State가 Attack State일 때만 활성화되도록 수정.

  • Enemy의 Chasing State를 구현할 때 MoveToPlayer 함수를 작성하는 과정에서 이상한 현상을 발견함.
    Player와 Enemy 모두 가만히 있을 때 중력이 비정상적으로 증가하는 현상이 발생.
    현재 코드에서는 Character Controller의 isGrounded 값이 true면 verticalVelocity를 0으로, false면 매 프레임마다 중력 가속도를 더하는 방식이었는데, 땅에 가만히 서 있으면 isGrounded를 false로 인식하면서 중력이 계속 강해짐.
    왜 그런가 찾아봤더니 Character Controller의 isGrounded는 Move 함수를 호출한 뒤에 상태가 갱신되기 때문에 isGrounded 값을 참조하기 전에 Move 함수를 호출해줘야 한다는 것이었음.
    코드의 순서를 재배치하는 것으로 오류를 해결함.

Move를 먼저 호출 (isGrounded를 true로 인식) Move를 나중에 호출 (isGrounded를 false로 인식)

오늘의 결과물


profile
Github: https://github.com/dlalsrn

0개의 댓글