147 lines
4.7 KiB
C#
147 lines
4.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Unity.HLODSystem.Utils;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.HLODSystem
|
|
{
|
|
public class FSM<T> where T : struct
|
|
{
|
|
private T m_currentState = default;
|
|
private T m_lastState = default;
|
|
private T m_transactionTargetState = default;
|
|
|
|
//event ordering
|
|
//exiting -> entering -> exited -> entered
|
|
class Functions
|
|
{
|
|
public Action EnteringFunction;
|
|
public Func<bool> IsReadyToEnterFunction;
|
|
public Action EnteredFunction;
|
|
|
|
public Action ExitingFunction;
|
|
public Func<bool> IsReadyToExitFunction;
|
|
public Action ExitedFunction;
|
|
}
|
|
|
|
private Dictionary<T, Functions> m_functions = new Dictionary<T, Functions>();
|
|
|
|
public T CurrentState => m_currentState;
|
|
public T LastState => m_lastState;
|
|
|
|
public void Update()
|
|
{
|
|
//transaction still progressing. have to check to finish.
|
|
if (Compare(m_currentState, m_transactionTargetState) == false)
|
|
{
|
|
if (GetFunctions(m_currentState).IsReadyToExitFunction?.Invoke() == false)
|
|
return;
|
|
if (GetFunctions(m_transactionTargetState).IsReadyToEnterFunction?.Invoke() == false)
|
|
return;
|
|
|
|
//the transaction has been finished.
|
|
GetFunctions(m_currentState).ExitedFunction?.Invoke();
|
|
GetFunctions(m_transactionTargetState).EnteredFunction?.Invoke();
|
|
|
|
m_currentState = m_transactionTargetState;
|
|
}
|
|
|
|
Debug.Assert(Compare(m_currentState, m_transactionTargetState));
|
|
|
|
//Here the transaction is always complete.
|
|
//We have to check to start a new transaction.
|
|
if (Compare(m_currentState, m_lastState) == false)
|
|
{
|
|
StartTransaction(m_currentState, m_lastState);
|
|
}
|
|
}
|
|
|
|
public void ChangeState(T state)
|
|
{
|
|
m_lastState = state;
|
|
if (Compare(m_currentState, m_lastState))
|
|
return;
|
|
|
|
//it means, completed the last transaction. we should do it immediately.
|
|
if (Compare(m_currentState, m_transactionTargetState))
|
|
{
|
|
StartTransaction(m_currentState, m_lastState);
|
|
}
|
|
}
|
|
|
|
public void RegisterEnteringFunction(T state, Action func)
|
|
{
|
|
GetFunctions(state).EnteringFunction = func;
|
|
}
|
|
public void UnregisterEnteringFunction(T state)
|
|
{
|
|
GetFunctions(state).EnteringFunction = null;
|
|
}
|
|
|
|
public void RegisterIsReadyToEnterFunction(T state, Func<bool> func)
|
|
{
|
|
GetFunctions(state).IsReadyToEnterFunction = func;
|
|
}
|
|
public void UnregisterIsReadyToEnterFunction(T state)
|
|
{
|
|
GetFunctions(state).IsReadyToEnterFunction = null;
|
|
}
|
|
public void RegisterEnteredFunction(T state, Action func)
|
|
{
|
|
GetFunctions(state).EnteredFunction = func;
|
|
}
|
|
public void UnregisterEnteredFunction(T state)
|
|
{
|
|
GetFunctions(state).EnteredFunction = null;
|
|
}
|
|
|
|
public void RegisterExitingFunction(T state, Action func)
|
|
{
|
|
GetFunctions(state).ExitingFunction = func;
|
|
}
|
|
public void UnregisterExitingFunction(T state)
|
|
{
|
|
GetFunctions(state).ExitingFunction = null;
|
|
}
|
|
public void RegisterIsReadyToExitFunction(T state, Func<bool> func)
|
|
{
|
|
GetFunctions(state).IsReadyToExitFunction = func;
|
|
}
|
|
public void UnregisterIsReadyToExitFunction(T state)
|
|
{
|
|
GetFunctions(state).IsReadyToExitFunction = null;
|
|
}
|
|
public void RegisterExitedFunction(T state, Action func)
|
|
{
|
|
GetFunctions(state).ExitedFunction = func;
|
|
}
|
|
public void UnregisterExitedFunction(T state)
|
|
{
|
|
GetFunctions(state).ExitedFunction = null;
|
|
}
|
|
|
|
private Functions GetFunctions(T state)
|
|
{
|
|
if ( m_functions.ContainsKey(state) == false )
|
|
m_functions.Add(state, new Functions());
|
|
|
|
return m_functions[state];
|
|
}
|
|
|
|
private void StartTransaction(T current, T target)
|
|
{
|
|
m_transactionTargetState = target;
|
|
|
|
GetFunctions(current).ExitingFunction?.Invoke();
|
|
GetFunctions(target).EnteringFunction?.Invoke();
|
|
}
|
|
|
|
private static bool Compare(T lhs, T rhs)
|
|
{
|
|
return EqualityComparer<T>.Default.Equals(lhs, rhs);
|
|
}
|
|
|
|
}
|
|
|
|
} |