-
Notifications
You must be signed in to change notification settings - Fork 0
/
MiniFSM.cs
68 lines (53 loc) · 1.96 KB
/
MiniFSM.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using System.Collections.Generic;
using UnityEngine;
public class MiniFSMHandler<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable {
public virtual TEnum State { get; set; }
public virtual Action Enter { get; set; }
public virtual Action Update { get; set; }
public virtual Action Exit { get; set; }
}
public class MiniFSM<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable {
private TEnum _currentState;
private TEnum _previousState;
private MiniFSMHandler<TEnum> _currentHandler;
private readonly Dictionary<TEnum, MiniFSMHandler<TEnum>> machineStates = new Dictionary<TEnum, MiniFSMHandler<TEnum>>();
public event Action<TEnum, TEnum> OnStateChanged;
public MiniFSM(params MiniFSMHandler<TEnum>[] states) {
foreach (MiniFSMHandler<TEnum> state in states) {
Add(state);
}
}
public void StartMachine(TEnum initialState) {
if (!machineStates.ContainsKey(initialState)) return;
_currentState = initialState;
_currentHandler = machineStates[initialState];
machineStates[initialState].Enter();
}
public void Add(MiniFSMHandler<TEnum> state) {
if (machineStates.ContainsKey(state.State)) {
Debug.LogError($"Already contains {state.State}");
return;
}
machineStates.Add(state.State, state);
}
public void Update() {
_currentHandler.Update();
}
public void ChangeState(TEnum nextState) {
// avoid changing to the same state
if (EqualsState(_currentState, nextState)) return;
_previousState = _currentState;
_currentState = nextState;
_currentHandler = machineStates[_currentState];
// exit the prev state, enter the next state
machineStates[_previousState].Exit();
_currentHandler.Enter();
// fire the changed event if we have a listener
OnStateChanged?.Invoke(_previousState, _currentState);
}
private static bool EqualsState(TEnum first, TEnum second) {
var asEnumType = first as TEnum?;
return EqualityComparer<TEnum>.Default.Equals(asEnumType.Value, second);
}
}