Unity - FSM(Finite State Machine)(3)

2024. 6. 20. 20:14Unity/Unity 학습정리

  마지막으로 FSM이 실제로 어떻게 상태가 변환되는 과정 및 결과이다. 개인적으로 이 부분이 FSM에 있어서 중요하다고 생각되는데, 어떤 상태를 가지던 해당 상태는 다른 상태로 이전될 수 있는 조건을 가지고 상태전이를 하는 과정을 겪는다.

 

 


 

  • Idle 상태 : 적을 발견하면 Chasing
public override void Update()
{
    base.Update();
    if(IsInChasinginRange())
    {
        stateMachine.ChangeState(stateMachine.chasingState);
        return;
    }
}

protected bool IsInChasinginRange()
{
    if (stateMachine.target == null) return false;
    float enemyDistanceSqr = (stateMachine.target.transform.position - stateMachine.player.transform.position).sqrMagnitude;
    return enemyDistanceSqr <= stateMachine.player.data.AttackData.EnemyChasingRange * stateMachine.player.data.AttackData.EnemyChasingRange;
}
  • Enemy가 플레이어가 탐지하는 범위내에 존재하면 상태를 ChasingState로 전환해주는 방식이다.
  • "범위"는 PlayerData가 소유하고있고 해당 데이터에 접근해서 거리계산을 해준다.
  • Chasing 상태 : 적이 공격범위내면 공격하고 그렇지 않다면 계속 Chasing상태를 유지, 범위에서 적이 사라지거나 없어지면 다시 Idle상태로 돌아감
public override void Update()
{
    base.Update();
    if (stateMachine.target == null || !IsInChasinginRange())
    {
        stateMachine.ChangeState(stateMachine.idleState);
        return;
    }
    if (IsInAttackinRange())
    {
        stateMachine.ChangeState(stateMachine.attackState);
        return;
    }
}

protected bool IsInAttackinRange()
{
    if (stateMachine.target == null) return false;
    float enemyDistanceSqr = (stateMachine.target.transform.position - stateMachine.player.transform.position).sqrMagnitude;
    return enemyDistanceSqr <= stateMachine.player.data.AttackData.AttackRange * stateMachine.player.data.AttackData.AttackRange;
}
  • 예외처리를해서 target이 존재하지않거나 범위가 없다면 IdleState로 돌아온다
  • 공격범위내에 있다면(IsInChasingRange 와 동작 방식은 같고 범위만 다름) attackState로 전환한다.
  • Attack 상태 : 만약 계속해서 공격범위내에 있다면 attckstate유지, 그렇지 않다면 범위내에 적이 있는지 탐지하고 있다면 ChasingState 그렇지 않다면 IdleState로 돌아간다.
public override void Update()
{
    base.Update();
    if (IsInAttackinRange()) return; //조건 더 추가해서 계속 몬스터를 추적시켜야함 가까이 있을경우
    if(IsInChasinginRange())
    {
        stateMachine.ChangeState(stateMachine.chasingState);
        return;
    }
    else
    {
        stateMachine.ChangeState(stateMachine.idleState);
        return;
    }
}

상태가 전이되는 방식과 조건을 정해서 코드를 구현해봤는데, FSM이 편하다는게 느껴졌다.

애니메이션도 따로 처리할 필요없이 묶어서 상태와 한번에 처리해서 사용하면서 편했다. 상태가 존재할 때 원하는 동작을 바로 적용시킬 수 있고, Update를 통해서 하위 State에 있는 노드들만 따로 처리하고 다시 상위 State로 전이되었을 때 해당 로직을 실행하지 않는다는 장점도 있는 것 같다. 

 

  물론 단점도 존재한다. 두 가지 상태를 동시에 가지고 싶은 경우가 있을 수 있는데 상태를 병렬적으로 가져가지 못한다는 점, 상태가 매우 복잡한 객체에 대해서는 FSM을 사용하면 전이에 대한 로직만으로도 코드가 복잡 해 질 수 있다는 점이 있다.

  이번 프로젝트에서는 플레이어가 Idle, Chasing, Attack 세 가지 로직만 가지기 때문에 FSM을 사용해 가독성을 높이고 상태 관리가 원할하게 코드를 구현하려고 노력했던 것 같다.

 

 

'Unity > Unity 학습정리' 카테고리의 다른 글

FSM StateMachine 상속  (0) 2024.07.01
Unity - Behaviour Tree (1)  (0) 2024.06.25
Unity - FSM(Finite State Machine)(2)  (0) 2024.06.18
Unity - FSM(Finite State Machine)(1)  (0) 2024.06.17
Unity - 슬라이더바로 사운드 조절하기  (1) 2024.06.05