본문 바로가기
# 게임/# Unity

FSM #2

by 쁘레레레레레 2020. 9. 14.

FSM을 만든지는 거의 한달쯤 됐는데 그간 포트폴리오 작업물을 촬영해서 올리려 할때마다 이상한 버그들이 터져버리는 바람에 계속 못쓰다가 이제 몰아쓴다.

 

1. 대기상태

2. 일정 대기시간이 지났을 경우 현재 방향으로 계속 걸어간다.

2-1. 만일 적(플레이어)이 발견된다면 chase실행

2-2. 범위가 좁혀졌다면 공격준비상태.

2-3. 공격

3. 만일 적(플레이어)이 범위를 벗어났다면 idle로 돌아가게 할 생각이다.



이전글에 이와같이 계획을 세웠고 일반몹 / 보스몹 따로 스크립트를 만들어 작성했다.

 

FSM은 하나의 상태를 가지고 있고 상태 전이에 대한 설계이고, 상태전이를 좀 더 매끄럽게 진행하기 위해기존 코드를 폐기한 후 애니메이터 내 addBehaviour에서 스크립트를 작성했다.

 

때문에 MonoBehaviour를 상속받는것이 아닌, StateMachineBehaviour를 상속받는다.

 

 

일반몹의 구성상태다.기본(idle)상태에서 일정 범위안에 플레이어 발견시 follow상태가 되고, 공격범위 안에 들어오면 공격 준비상태인 (ready) 상태가 되었다가 attack을 한다. 이후에 플레이어가 시야에서 사라지면 follow -> back -> idle 상태가 된다.

 

tmi로 back상태의 경우, 이름을 잘못지었는데 Wander가 더 어울린다. (일정 시간마다 좌,우 방향을 정한 후 일정 거리를 걸어가기 때문)

 

idleState -

 

public class idleState : StateMachineBehaviour
{
    Transform enemyTransform;
    Enemy enemy;
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        enemy = animator.GetComponent<Enemy>();
        enemyTransform = animator.GetComponent<Transform>();
    }

    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        if(Vector2.Distance(enemyTransform.position, enemy.player.position) <= 4)
        {
            animator.SetBool("isFollow", true);
        }
    }
}
public class attackState : StateMachineBehaviour
{
    Enemy enemy;
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        enemy = animator.GetComponent<Enemy>();
    }

    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Weapon weapon = enemy.GetComponent<Weapon>();
        if (enemy.attackDelay <= float.Epsilon)
        {
            weapon.FireAmmo(enemy.player.position);
            enemy.attackDelay = enemy.attackCoolDown;
        }
    }

    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        enemy.nAttackCount = 1;
    }
}

 

 

위 코드는 idleState와 attackState인데,

평소 코드처럼 사용할 변수를 불러올 부분은 Enter에서 불러와 준 후

Update에서 조건을 걸어주면 된다.

 

일반몹과 보스몹 둘 다 공격 쿨다운이 존재한다.

 

일반몹의 경우 발사체를 이용해 공격을 하고

 

보스몹의 경우 근거리 공격이다. 게임 특성상 관대한 공격 범위를 적용해서

 

근거리 공격을 사용하는 플레이어,보스몹에게 보이는것보다 조금 더 큰 공격용 콜라이더를 적용했다.

 

 

 

 

보스의 경우 설계를 살짝 달리했다.

일반몹의 경우 체력값이 낮아 플레이어에게 한방으로 죽기때문에 hurt를 쓰진 않았지만

보스몹의 경우 운이 좋아 데미지 상승 아이템을 4개 이상 먹었을 경우가 아니면 한두번으론 죽지 않는다.

때문에 별것없지만 더 이상한 설계를 했다.

 

기존 일반몹은 attack트리거 하나와  몹의 방향 값, 따라가는중인지, 돌아다니는중인지 판단하는 값이 있는 반면

 

보스몹의 경우 행동 값을 float로 정해놨고 땅을 딛고있는지, 정찰중인지, 플레이어를 쫓아가는 중인지를 판단하는 값과

death,hurt,attack의 트리거가 있다.

 

여기서 float로 설정되어있는 behaviour를 설명하자면 Wander를 조금 다르게 설정해봤다.

 

블렌트 트리를 이용해서 각 행동을 구성했다.

 

위와 같이 값에 따라서 부드럽게? 행동값이 바뀌게 된다.

 

유저가 근처에 있지 않으면 스스로 방향을 전환한 후 앞으로 가거나, 공격준비 상태가 되거나, 가만히 있는 상태가 된다.

'# 게임 > # Unity' 카테고리의 다른 글

각 종 컴포넌트에 접근하기  (0) 2022.04.29
[Project Freud] 유니티개발 두번째 게임 (취소됨)  (0) 2022.02.17
FSM #1  (0) 2020.08.04
Procedural Dungeon Generation in Unity #4 점검  (0) 2020.07.30
움직임 입력값  (0) 2020.07.29