Code/k/GoalStateMachine.cs
using System;
using Sandbox.k.Interfaces;
namespace Sandbox.k
{
[Serializable]
public class GoalStateMachine<T> : IStateMachine<T> where T : IGoalState
{
[Property] private T _currentGoalState;
public T CurrentState => _currentGoalState;
public Action<T> OnStateChange;
private Func<T, bool> _onBeforeChangeState;
private Func<T, bool> _onAfterChangeState;
public virtual bool Init(T initialState,
Func<T, bool> onBeforeChangeState = null,
Func<T, bool> onAfterChangeState = null)
{
_onBeforeChangeState = onBeforeChangeState;
_onAfterChangeState = onAfterChangeState;
if (initialState != null)
ChangeState(initialState);
return true;
}
public bool ChangeState(T newState)
{
if (_onBeforeChangeState != null
&& !_onBeforeChangeState.Invoke(_currentGoalState))
return false;
_currentGoalState?.Exit();
newState.Enter();
OnStateChange?.Invoke( newState );
_currentGoalState = newState;
if (_onAfterChangeState != null
&& !_onAfterChangeState.Invoke(_currentGoalState))
return false;
return true;
}
public bool Refresh()
{
if (_currentGoalState == null)
return true; // means nothing to do
_currentGoalState.Execute();
if (_currentGoalState.IsGoalComplete())
{
ChangeState((T)_currentGoalState.GetNextState());
}
return true;
}
}
}