본문 바로가기

Unity

[Unity3D]FSM을 활용한 AI개발(3)

1. 서론

우선 체크해야 할 일은 좀비, 군인, 시민은 모두 다 같은 형태 일 것을 파악하고 있어야 한다.

 

우리는 그래서 추상 키워드와 제너릭 키워드를 사용해야 하고 알아야 할 필요가 있다.

추상 키워드와 제너릭 키워드는 다른 글에 설명을 쓰도록 하겠다.

2. 본론

//FSM.cs
namespace MyFSM
{
    abstract public class FSM<T>
    {
        abstract public void Begin();
        abstract public void Run();
        abstract public void Exit();
    }
}

각 상태들이 상속받을 FSM추상 클래스를 만든다. 이렇게 밑 작업을 해두면 계속해서 상태들을 만들어 내는데 실수도 덜고 작업 속도가 조금 향상될 수 있다고 믿는다.

 

Begin() 함수에선 각 상태들을 초기화할 예정이며, Run() 함수에서는 각 상태들을 실 동작 부를 구현 할 것이고,

Exit() 함수에서는 종료되는 시점에 해야 할 일들을 채워 나갈 것이다.

 

다음은 Machine 기능을 담당하는 클래스이다.

//Head_Machine.cs

using UnityEngine;

namespace MyFSM
{

    public class Head_Machine<T>
    {
        //오브젝트
        private T Owner;

        //상태 값
        private FSM<T> m_CurState = null;//현재
        private FSM<T> m_PrevState = null;//이전

        //첫 상태값
        public void Begin()
        {
            if (m_CurState != null)
            {
                m_CurState.Begin();
            }
        }

        //상태 업데이트
        public void Run()
        {
            CheckState();
        }


        public void CheckState()
        {
            if (m_CurState != null)
            {
                m_CurState.Run();
            }
        }

        //fsm종료
        public void Exit()
        {
            m_CurState.Exit();
            m_CurState = null;
            m_PrevState = null;
        }

        public void Change(FSM<T> _state)
        {
            //같은 상태를 변화...는 리턴
            if (_state == m_CurState)
                return;

            m_PrevState = m_CurState;

            //현재 상태가 있다면 종료
            if (m_CurState != null)
                m_CurState.Exit();

            m_CurState = _state;
            //새로 적용된 상태가 널이 아니면 실행
            if (m_CurState != null)
                m_CurState.Begin();
        }

        //변화할땐 아무런 인자값이 없으면 전에 상태값을 출력한다
        public void Revert()
        {
            if (m_PrevState != null)
                Change(m_PrevState);
        }

        //상태값세팅
        public void SetState(FSM<T> _state, T _Owner)
        {
            Owner = _Owner;
            m_CurState = _state;

            //들어온 상태값이 지금과 다를때, 현재상태값이 채워져 있을때
            if (m_CurState != _state && m_CurState != null)
                m_PrevState = m_CurState;
        }
    }
}

각 상태 값들이 잘 들어왔는지 체크하고, 있으면 현재 상태에, 없으면 이전 상태에 값을 넣고 각 상태의 Begin을 호출하거나 Run상태를 루프 돌리며, Exit를 호출해 다음 상태로 바꿀 준비를 한다.

3. 결론

이번 글은 각 상태 값들이 어떤 동작 방식을 가지는지, 그 상태 값을 어떻게 바꿀지에 대해 알아보았다.

 

다시 한번 정리하자면, 상태 값은 제일 먼저 초기화를 거치고 나면, Run 상태들을 계속 돌다가, Exit를 호출해서 해당 상태의 값을 마무리한다. 아주 단순한 동작 이므로 이해하는데 어려움이 없을 것으로 예상된다.

 

기본 제공된 머신 코드들은 많으니 다른 것들도 참고 해 보길 바란다. 아마, 대부분 비슷한 머신 코드들 일 것이다.

 

다음 글은 각 오브젝트가 가져갈 상태 값과 브레인 값을 알아보도록 하겠다.