게임 프로그래밍을 공부했다면, 혹은 CS를 2학년까지 수료했거나 이산수학같은 과목을 들었다면 FSM이라는 친구를 한번 쯤은 들어봤을 것이다. FSM은 무신교가 종교를 강요하고 다니는 사람을 비꼬기 위해 만든 날아다니는 스파게티 괴물(Flying Spaghetti Monster)라는 친구도 있지만 CS에서, 수학에서는 유한 상태 기계(Finite State Machine)이라는 친구이다.
앞으로 주변에있는 Sample 크기 이상의 게임을 만들때는 FSM이라는 개념을 알아두면 게임을 구성하고 진행하는데 많은 도움이 될 것이고, 이미 어느정도 만들어져있는 프로젝트에 참여하게된다면 이미 FSM을 적극적으로 활용하고 있는 경우가 많을 것이다. 때문에라도 FSM을 배우고 이것을 게임엔진에서 어떻게 구현할수있는 지를 익혀두면 많은 도움이 될 것이다. 실제로 병역 특례 면접을 보던 회사들중에 FSM에 대해서 알고 있냐는 질문을 많이 받았고, 지금 입사한 회사에서도 FSM을 적극적으로 이용하고 있다.
FSM이란 무엇인가?
유한 상태 기계는 유한한 갯수의 상태(State)를 가지고 있는 기계라는 의미로, 기계는 한 개의 상태만 유지할 수 있고 그 상태에 맞는 특별한 이벤트나 상황이 되었을 때 다른 상태로 전이하여 자신의 일을 수행하는 특징을 가진다. 수학적으로는 상태 하나 하나가 Node로 이루어져 있고, 상태와 상태 사이의 전이는 Edge로 이루어져있는 '그래프'의 모양을 띄게된다. 역시 말로하는 것보다는 그림으로 보는게 이해가 빠르므로 아래의 그림을 살펴보자
게임의 전체적인 그림을 FSM으로 나타낸 것이다. '시작 화면', '대기 화면', '인 게임'은 각각의 상태들이고 '게임 시작 버튼 Click', '던전 입장 버튼 Click', '사망', '클리어'는 각각의 상태가 전이되는 조건들을 나타낸 것이다. 큰 그림에서 게임에 필요한 상태들을 먼저 정의하고 그 상태들의 전이 조건들을 정해둔다면, 각 상태별로 진행해야하는 로직들이나 필요한 객체들을 차례차례 구현해나가면 된다.
FSM은 어떻게 만드나요?
여러가지 방법이 있을 수 있다. 기본적으로는 State 패턴이라는 친구로 상태를 만들고 전이조건들을 만들어 사용을 한다. 하지만 유니티에서는 Coroutine을 이용한 상태 조절을 사용하는 것같다. 코루틴 하나를 상태로 보고 Enum으로 정의해두었다가 Enum to String을 통하여 다른 코루틴으로 넘어갈 수 있게 만들어 마치 FSM이 작동하는 것처럼 보이게 할 수 있다. 실제로 코루틴을 설명하거나 강의 영상의 샘플들을 보면 코루틴으로 FSM을 만드는 예제가 여럿있다.
코루틴에 대해서 좀더 알아보고 싶거나 코루틴을 이용하여 어떻게 FSM을 만들 수 있는지는 아래에 있는 피피티를 통해한번 훑어볼 수 있다. FSM은 슬라이드 뒤 쪽 예시에서 살펴볼 수 있음 (이미 어느정도 지식이 있다면 넘어가도 좋음)
FSM이 커지면 관리는?
하지만, 코드로만 FSM을 제작하고 유지보수하고 확장하려고하면 여러가지 문제가 있을 수 있다. 단편적으로 상태와 전이 조건이 많이질 수록 한번에 전체적인 FSM의 형태를 떠올리기가 쉽지 않다. 그래프의 형태를 코드로만 확인하려하기 때문에 당연한 일이다. 그럼 좀 더 편리한 방법은 없을까?
FSM은 오래 전부터 게임프로그래밍에 사용해왔기 때문에 도움을 줄 여러가지 툴이 있다. 대표적으로 유니티의 Playmaker나 nodeCanvas같은 유료플러그인 들이다. 이 플러그인들은 FSM을 눈으로 볼 수 있는 그래프 형태로 만들고 안에서 돌아가는 로직들 까지도 노드를 이용해서 제작할 수 있게 만들어져있다. FSM을 코드뿐만 아니라 그래프의 형태로 눈에 익히고 사용할 수 있도록 도와주는 것이다.
위 두가지 툴은 현업에서도 사용할 수 있을 만큼 잘 만들어진 플러그인이기 때문에 가격도 조금 있는 편이다. 하지만 확실하게 FSM 하나가 어떤 플로우를 가지고 동작하는지 눈으로 파학하기 편하고 그만큼 코드를 작성하는데 편리한 점이 많다. 물론 꼼꼼한 주석과 문서화를 통해 이런 툴을 사용하지 않고도 FSM을 만들고 관리할 수는 있지만 세상은 돈을 지불한 만큼 편해지기는 한다.
마치며
이번 디자인 패턴은 원래 State 패턴에 대해서 다루려했지만, Unity는 Coroutine이라는 개념과 잘 만들어져있는 여러 플러그인이 있기 때문에 State 패턴을 직접 코드로 만져보는 것이 아니라 FSM이라는 친구가 있다는 점과 대략 어떻게 동작하는 개념이며, 코드로는 유니티에서 코루틴과 Enum을 사용하여 제작하고 이 것이 불편하다면 이미 잘 만들어져있는 플러그인이 있다는 것을 아는 것으로 충분하다고 생각하여 대략적인 개념만 소개했다.
요약하면
0. FSM이라는 친구는 게임을 만들면서 보게될 친구이고, ~~ 이러한 개념으로 이루어져있다
1. 이 친구는 State 패턴을 사용하거나 유니티에서 Coroutine + Enum을 통해 구현하고 있다
2. 이 것이 불편하면 유니티에는 FSM을 간단하게 작성할 수 있는 툴이 많다
정도일 것 같다.