Unity3D에서 C# Script로 FSM (Finite State Machine) 구현
1. FSM 구현을 위해 Unity3D engine 이 제공하는 StartCoroutine 메서드 활용.
Unity > Support > Script Reference > MonoBehaviour.StartCoroutine 참고
Unity3D engine 에서 제공하는 MonoBehaviour 객체의 StartCoroutine 메서드는 매 프레임 마다 지정 된 콜백함수를 실행합니다.
Debug.Log 를 찍어서 확인 해 보시면, Update, StartCoroutine 에서 지정 된 콜백함수 순으로 실행이 됩니다.
이때 지정 된 콜백 함수가 IEnumerator 를 반환하는 형태이기 때문에 while 문과 yield 키워드를 통해 FSM 을 구현 할 수 있습니다.
2. State 정의 및 IEnumerator 를 반환하는 State 별 함수 구현.
- State 정의
우선, FSM 이 되는 객체에 State 를 정의 합니다. (귀찮아서 세밀하게 구현 하는 것보단 심플하게 어떻게 동작하는지 보여드리는게 더 효과적일 것 같아서 Init, Idle, Move 로만 정의했습니다.)
Init,
Idle,
Move
}
- State 별 함수 구현
FSM을 구현하기 위해 3가지의 메서드가 필요합니다. (State 최초 진입 시 실행 될 메서드, 매 프레임마다 실행 될 메서드, State 종료시 실행 될 메서드)
만약, StartCoroutine 메서드가 없다면 각 메서드를 구현 해 주고, State 변경 메서드를 따로 두어 관리해야 하겠지만, Unity3D engine 을 사용 시에는 더욱 더 편하게 3개의 메서드를 하나로 통합 할 수 있으며, 클래스 상속을 통해 메서드를 상속, 오버라이드 하여 유연하게 구현하는 장점이 생기죠.
방법은 다음과 같습니다.
// Enter
this.gameObject.animation.Play("Take 001");
yield return null;
while (this.State == DudeState.Move) {
// Excute
this.gameObject.transform.position +=
new Vector3(0, 0, Time.deltaTime * moveSpeed);
if (!moving) {
this.State = DudeState.Idle;
}
yield return null;
}
// Exit
NextState();
}
IEnumerator 를 반환하고 yield 키워드를 사용하는 이유는 이렇습니다.
StartCoroutine에 콜백함수가 지정되면, 지정 된 콜백함수는 매프레임마다 Update 문 다음에 실행됩니다. 이 때, yield 문을 만나면 콜백함수 내에서 yield 다음 구문을 다음 프레임으로 양보하고 콜백함수가 종료가 됩니다. 그러면 또 다음번 프레임에서는 yield 문 다음 구문이 실행이 되는 것이죠.
그래서 위와 같이 콜백함수를 코딩하면,
- State 최초 진입 시 실행 되는 블럭 (Enter 부분, while 문 이전까지)
- 매 프레임 마다 실행 되는 블럭 (Execute 부분, While 문 블럭)
- State 종료 시 실행 되는 블럭 (Exit 부분, while문 블럭 이하)
이렇게 구현이 되는 것이죠.
3. 각 State 에 맞는 StartCoroutine 의 콜백함수(2.번에서 구현 된)를 지정.
string methodName = State.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
요약
1. FSM 구현을 위해 Unity3D engine 이 제공하는 StartCoroutine 메서드 활용.
2. State 정의 및 IEnumerator 를 반환하는 State 별 함수 구현.
3. 각 State 에 맞는 StartCoroutine 의 콜백함수(2.번에서 구현 된)를 지정.
Unity 샘플 프로젝트를 첨부합니다.