public abstract class State // 추상(abstract) 클래스로 구현
{
// 해당 상태를 시작할 때 1회 호출
public abstract void Enter(Student entity);
// 해당 상태를 업데이트할 때 매 프레임 호출
public abstract void Execute(Student entity);
// 해당 상태를 종료할 때 1회 호출
public abstract void Exit(Student entity);
}
public enum StudentStates // 플레이어가 가질 수 있는 상태
{RestAndSleep, StudyHard, TakeAExam, PlayAGame, HitTheBottle}
public class Student
{
// Student의 속성들
private int knowledge; // 지식
private int stress; // 스트레스
private int fatigue; // 피로
private int totalScore; // 총 점수
private Locations currentLocation; // 현재 위치
// Student가 가지고 있는 모든 상태, 현재 상태
private State[] states;
private State currentState;
public void SetUp(string name)
{
// states에 State 클래스 형식의 객체가 5개 들어가는 배열 대입
states = new State[5];
// states의 각 인덱스에 각 클래스 메모리 할당
states[(int)StudentStates.RestAndSleep] = new StudentOwnedStates.RestAndSleep();
states[(int)StudentState.StudyHard] = new StudentOwendStates.StudyHard();
states[(int)StudentState.TakeAExam] = new StudentOwendStates.TakeAExam();
states[(int)StudentState.PlayAGame] = new StudentOwendStates.PlayAGame();
states[(int)StudentState.HitTheBottle] = new StudentOwendStates.HitTheBottle();
// 현재 상태를 RestAndSleep 상태로 설정
ChangeState(StudentStates.RestAndSleep);
knowledge = 0;
stress = 0;
fatigue = 0;
totalScore = 0;
currentLocation = Location.SweetHome;
}
public void Updated()
{
// currentState가 비어있지 않으면 현재 상태의 Execute 메서드 실행
if(currentState != null)
currentState.Execute(this); // this는 Student 클래스 객체
}
public void ChangeState(StudentStates newState)
{
// 새로 바꾸려는 상태가 비어있으면 상태를 바꾸지 않고 return
if(states[(int)newState] == null) return;
// 현재 상태를 종료하기 위해 Exit() 메소드 호출
if(currentState != null)
currentState.Exit(this);
// 새로운 상태로 변경하고, 새로 바뀐 상태의 Enter() 메서드 호출
currentState = states[(int)newState]
currentState.Enter(this);
}
}
nameSpace StudentOwnedStates
{
public class RestAndSleep : State // State 클래스를 상속받음.
{
public override void Enter(Student entity) // 시작 행동
{
// 장소를 집으로 설정하고, 집에 오면 스트레스가 0이 된다.
entity.currentLocation = Location.SweetHome;
entity.stress = 0;
}
public override void Execute(Student entity) // 지속 행동
{
// 피로가 0보다 크면 지속적으로 피로 10씩 회복
if(entity.fatigue > 0)
entity.fatigue -= 10;
else
{
// StudyHard 상태로 변경
entity.ChangeState(StudentStates.StudyHard);
}
}
public override void Exit(Student entity) {} // 종료 행동 없음
}
public class StudyHard : State
{
public override void Enter(Student entity)
{
entity.currentLocation = Location.Library;
}
public override void Execute(Student entity)
{
entity.knowledge++;
entity.stress++;
entity.fatigue++;
// entity의 knowledge가 3 ~ 10 사이면
if(entity.knowledge >= 3 && entity.knowledge <= 10)
{
int isExit = Random.Range(0, 2);
// isExit가 1이거나 knowledge가 10이면
if(isExit == 1 || entity.knowledge == 10)
{
// 현재 상태를 TakeAExam 상태로 변경
entity.ChangeState(StudentStates.TakeAExam);
}
}
if(entity.stress >= 20)
{
// 현재 상태를 PlayAGame 상태로 변경
entity.ChangeState(StudentStates.PlayAGame);
}
if(entity.fatigue >= 50)
{
// 현재 상태를 RestAndSleep 상태로 변경
entity.ChangeState(StudentStates.RestAndSleep);
}
}
public override void Exit(Student entity) {} // 종료 행동 없음
}
// 나머지 클래스들도 구현
public class TakeAExam : State
{...}
public class PlayAGame : State
{...}
public class HitTheBottle : State
{...}
}
출처 : 고박사의 유니티 노트 - FSM2 (링크)