[ Pattern ] State Pattern(상태 패턴) in Unity C#

[ Programming Pattern 시리즈 ]
싱글턴 패턴 (Singleton Pattern) Link
컴포넌트 패턴 (Component Pattern) Link

커멘드 패턴 (Command Pattern) Link
관찰자 패턴 (Observer Pattern) Link
상태 패턴 (State Pattern) Link

CS 전공이라면 오토마타 수업은 한번 쯤 들어보거나, 한 다리 건너 들어 보긴 했을 것이다. 유한 상태 기계 (Finite State Machine)는 State 패턴의 개념과 동일하다. 상태 패턴의 GoF 정의는 아래와 같다.

“객체의 내부 상태에 따라 스스로 행동을 변경할 수 있게 허가하는 패턴으로, 이렇게 하면 객체는 마치 자신의 클래스를 바꾸는 것처럼 보입니다.”

유니티의 Animator Controller는 FSM, 즉 상태 패턴의 전형적인 구현이다.

%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2016-12-01-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-3-45-06

상태 패턴은 여러 방식으로 구현이 가능하다. 아래는 간단하게 구현한 하나의 예이다.  / Original Source Link

코루틴 안에서 코루틴을 호출해서 코루틴이 자신이 호출한 코루틴이 종료되기를 기다리는 형태이다. 해당 코루틴이 종료되는 순간, 즉 해당 State의 실행이 끝나는 순간에 다시 호출 되면서 새로운 State의 실행 코루틴을 호출하게 된다.

 

그리고 아래는 조금 더 다양한 상황을 설정해서, State의 Kill도 가능하도록  구현해 본 상태 패턴이다.

거동은 몬스터가 패트롤을 하다가 시야에 캐릭터가 들어오면 추적한다. 그리고 추적하다가 캐릭터가 시야에서 벗어 날 경우 근처를 둘러보는 Investigate 상태에 들어간다. 그리고는 다시 패트롤 상태로 가는 3가지 상태가 존재한다.

거동 플레이를 영상으로 보면 아래와 같다.

그리고 상태 패턴이 적용된 몬스터 클래스이다.

<Monster.cs>

위의 코드와 같이 상태 패턴을 만들 수도 있고, 또 다르게 만들 수도 있다. NavMesh Agent를 사용하여 Chasing하게 하는 코드 부분은 이 글의 핵심은 아니다. 핵심은 State 별로 모듈을 분리하여 서로 Coupling이 발생하지 않도록 분리해 주는 데 있다. 자연히 State를 정의하는 enum 형태의 변수가 존재하고, State를 Setting 하는 Method들이 들어간다. 그리고 일반 Method나 Class, Coroutine Method들로 Update 로직들을 분리 할 수 있게 된다. 위 클래스에서 Job 클래스는 Seeing과 Hearing을 Coroutine으로 돌려주는 클래스이다. 캐릭터가 시야에 들어왔는지, 주변에 있는지 체크한다.

 

 

Github Source Project Link : https://github.com/inbgche/UnityStatePattern
Reference: https://github.com/TomCoadjoint/coAdjoint_CSharp_Tutorials