본문 바로가기

Unity

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

1. 서론

그림1. 좀비 오브젝트

FSM이 오브젝트에 붙어 머신을 동작시키고 각 State를 어떻게 관리하는지 알아볼 것이다.

우선 첫 번째로 우리는 이 오브젝트가 어떤 상태 값을 가질 것인지, 어떤 데이터가 필요한 지부터 알아보자.

2. 본론

//ZombieFSM.cs
public class ZombieFSM : MonoBehaviour
    {
    	//머신에 들어갈 스테이트
        public Head_Machine<ZombieFSM> m_state;
        
        //좀비가 미리 가지고 있을 스테이트
        public FSM<ZombieFSM>[] m_arrState = new FSM<ZombieFSM>[(int)ZOMBIE_STATE.END];

		//좀비가 다른 오브젝트를 찾을 범위
        public float m_fFindRange;
        //좀비가 찾은 타겟
        public Transform m_TransTarget;

		//좀비의 현재상태, 이전상태
        public ZOMBIE_STATE m_eCurState;
        public ZOMBIE_STATE m_ePrevState;

		//좀비의 체력
        public int m_iHealth;
        //좀비의 공격 범위
        public float m_fAttackRange;
		
        //애니메이터
        public Animator m_Animator;

		//생성자
        public ZombieFSM()
        {
            Init();
        }

		//필요한 데이터 초기화
        public void Init()
        {
            m_state = new Head_Machine<ZombieFSM>();

            m_arrState[(int)ZOMBIE_STATE.Idle] = new Zombie_Idle(this);
            m_arrState[(int)ZOMBIE_STATE.Walk] = new Zombie_Walk(this);
            m_arrState[(int)ZOMBIE_STATE.Die] = new Zombie_Die(this);
            m_arrState[(int)ZOMBIE_STATE.Attack] = new Zombie_Attack(this);


            m_state.SetState(m_arrState[(int)ZOMBIE_STATE.Idle], this);
        }
        
        //상태 변화
        public void ChangeFSM(ZOMBIE_STATE ps)
        {
            for (int i = 0; i < (int)ZOMBIE_STATE.END; ++i)
            {
                if (i == (int)ps)
                    m_state.Change(m_arrState[(int)ps]);
            }
        }

        public void Begin()
        {
            m_state.Begin();
        }

        public void Run()
        {
            m_state.Run();
        }

        public void Exit()
        {
            m_state.Exit();
        }
        
        private void Awake()
        {
            m_Animator = this.GetComponent<Animator>();
        }

        private void Start()
        {
            Begin();
        }

        private void Update()
        {
            Run();

            m_fFindRange += Time.deltaTime;
            m_fFindRange = Mathf.Clamp(m_fFindRange , 10f, 500f);

            if (m_fFindRange >= 25f)
                m_fFindRange = 10f;
        }
... ...

우선 좀비가 필요로 하는 것이 무엇일까. 우리가 생성하는 FSM클래스는 어떤 데이터를 필요로 할까.

정말 복잡한 상태 값들을 가질 수 도 있겠지만, 우리는 단순히 좀비가 걷다 , 멈췄다, 공격하고, 죽길 원한다.

그러기 위해서는 좀비는 각 상태 값을 가지고 있을 필요가 있다. 

 

좀비가 가질 상태 값들을 배열로 준비해두고, 준비해두었던 상태값을 머신에 연결만 지어주면, 모든 준비는 되었다고 볼 수 있겠다.

 

그 후에 때에 맞게 상태값 변화와 시작 업데이트만 돌려준다면 끝이 난다.

 

그림2. Inspector 창

좀비 오브젝트에 Class를 붙여준 모습, 오브젝트의 찾는 범위, 체력, 공격 범위 등은 public으로 확인하면서 밸런싱을 맞춰주도록 하는 게 편하다. 추후 Target이나 Animator들은 [HideInstpector]으로 숨겨두는 처리를 하면 더 보기 편할 것이다.

 

그림3. FSM클래스 구조

대게 초보 개발자들이 하는 실수인 것인데. 뭉텅이 뭉텅이 정리해놓지 않으면 많인 기능들이 필요한 프로젝트의 경우 프로젝트가 개판 5분 전이 될 수 있다. 코드나 폴더나 정리는 개발자의 숙명인 것이다. 책상 정리는 하나도 안 하면서...

 

3. 결론

이 글에서는 오브젝트가 어떻게 상태 값을 미리 가지고, 그것들을 변화시킬 것인지 알아보았다.

다음 글에서는 FSM <T>를 상속받은 상태 값을 어떻게 정의하고, 어떻게 사용할 것인지 알아보겠다.

 

 

 

질문은 댓글로 적어주시면 최대한 빠르게 답글 달아 드리겠습니다.

또한 핵심 코드는 맨 마지막 글에 업로드 해 놓을 것이니 참고 부탁드리겠습니다.