Skip to content

Commit

Permalink
기본 문자열을 상태로 지정하는 기본 머신 추가 및 도움말과 예제 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
khchaCA committed Aug 18, 2024
1 parent fbde616 commit c520aba
Show file tree
Hide file tree
Showing 9 changed files with 743 additions and 4 deletions.
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,93 @@
# FiniteStateMachine

단순한 계층 유한 상태 머신(HFSM : Hierarchical Finite State Machine) 라이브러리 입니다.

## 목적

- 간단한 HFSM이 필요했으나 보통은 전환(Transition)을 통한 상태 변환을 하는 라이브러리 밖에 찾을 수가 없어서 제가 원하는 형태로 만들어 보았습니다.


## 사용


private FiniteStateMachine<STATE> _fsm;

private void Start()
{
_fsm = new FiniteStateMachine<STATE>();
var idleFSM = new FiniteStateMachine<STATE>(STATE.IDLE);
idleFSM.AddState(new RestState(), new EatState(), new SleepState());
_fsm.AddState(idleFSM, new MoveState(), new AttackState(), new DeadState());
_fsm.SetStartState(STATE.IDLE);
_fsm.Initialize();
}

private void Update()
{
_fsm.Update();
}

1. 상태를 정의할 타입을 선언합니다. (문자열을 사용해도 됩니다.)
```csharp
public enum STATE { NONE, IDLE, REST, EAT, SLEEP, MOVE, ATTACK, DEAD }
```

2. 상태 클래스와 서브 머신 클래스를 구현해 줍니다. (나머지 코드는 샘플을 확인하세요.)
```csharp
// 상태가 전환되고 1초 후에 서브 머신의 EAT 상태로 전환 됩니다.
public class RestState : BaseState<STATE>
{
public override STATE State => STATE.REST;

private float _enterTime;

public override void Enter()
{
Debug.Log($"Enter : {GetType()}");
_enterTime = Time.time;
}

public override void Update()
{
if (Time.time - _enterTime > 1f)
{
FSM.ChangeState(STATE.EAT);
return;
}
}
}
.
.
.
```

3. FSM을 생성하고 상태를 추가합니다. (서브 스테이트 머신도 동일한 타이밍에 생성하여 추가합니다.)

```csharp
using DarkNaku.FSM;

private FiniteStateMachine<STATE> _fsm;

private void Start()
{
_fsm = new FiniteStateMachine<STATE>();
var idleFSM = new FiniteStateMachine<STATE>(STATE.IDLE); // 서브 스테이트 머신 선언
idleFSM.AddState(new RestState(), new EatState(), new SleepState());
_fsm.AddState(idleFSM, new MoveState(), new AttackState(), new DeadState()); // 서브 스테이트 머신은 다른 상태와 동일하게 추가
_fsm.SetStartState(STATE.IDLE);
_fsm.Initialize();
}
```

4. 업데이트 주기마다 호출 FSM 갱신을 호출해 줍니다.
```csharp
private void Update()
{
_fsm.Update();
}
```

## 부가설명
* Transition은 지원하지 않습니다.
* Enter 이벤트 내부에서 ChangeState를 호출하여 프레임 손실 없이 상태를 전환 할 수 있으나 무한루프에 빠질 수 있으니 주의 하세요.(추후에 방지 코드를 넣을 예정)
* 서브 스테이스에서는 ParentFSM 속성을 통해 상위 머신에 접근할 수 있습니다.
19 changes: 16 additions & 3 deletions Runtime/FiniteStateMachine.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
Expand All @@ -18,7 +16,7 @@ public class TransitionEvent : UnityEvent<T, T>
{
}

public override T State => default(T);
public override T State => _state;

public IFiniteStateMachine<T> ParentFSM => FSM;

Expand All @@ -42,10 +40,21 @@ public BaseState<T> CurrentState {
}

private bool _initialized;
private T _state;
private T _start;
private T _current;
private T _next;
private Dictionary<T, BaseState<T>> _states = new Dictionary<T, BaseState<T>>();

public FiniteStateMachine()
{
_state = default;
}

public FiniteStateMachine(T state)
{
_state = state;
}

public void AddState(params BaseState<T>[] states)
{
Expand Down Expand Up @@ -162,4 +171,8 @@ private void ChangeStateIfNecessary()
ChangeStateIfNecessary();
}
}

public class FiniteStateMachine : FiniteStateMachine<string>
{
}
}
8 changes: 8 additions & 0 deletions Samples~/SampleFSM/Scenes.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c520aba

Please sign in to comment.