130 lines
4.2 KiB
C#
130 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEditor.UIElements;
|
|
#endif
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace BITKit.StateMachine
|
|
{
|
|
[Serializable]
|
|
public class MonoStateMachine<TState> : IStateMachine<TState> where TState : IState
|
|
{
|
|
public bool Enabled
|
|
{
|
|
get => _enabled;
|
|
set
|
|
{
|
|
_enabled = value;
|
|
if (CurrentState is null) return;
|
|
if (value)
|
|
{
|
|
CurrentState.OnStateExit(null,null);
|
|
}
|
|
else
|
|
{
|
|
CurrentState.OnStateEntry(null);
|
|
}
|
|
}
|
|
}
|
|
public TState CurrentState { get; set; }
|
|
public event Action<TState, TState> OnStateChanged;
|
|
public event Action<TState> OnStateRegistered;
|
|
public event Action<TState> OnStateUnRegistered;
|
|
|
|
[SerializeReference, SubclassSelector] public List<TState> states = new();
|
|
[SerializeField,ReadOnly] private string _currentStateName;
|
|
[SerializeField] private bool debug;
|
|
[SerializeField] private bool transitionOnNextFrame;
|
|
public IDictionary<Type, TState> StateDictionary { get; } = new Dictionary<Type, TState>();
|
|
private bool _enabled = true;
|
|
private readonly DoubleBuffer<TState> _nextState = new();
|
|
protected bool cancelUpdateStateThisFrame;
|
|
public void Initialize()
|
|
{
|
|
foreach (var state in states)
|
|
{
|
|
//state.TransitionState = InternalTransitionState;
|
|
state.Initialize();
|
|
StateDictionary.Add(state.GetType(), state);
|
|
}
|
|
// if (states.Count > 0)
|
|
// {
|
|
// TransitionState(states[0]);
|
|
// }
|
|
}
|
|
public void UpdateState(float deltaTime)
|
|
{
|
|
if(transitionOnNextFrame && _nextState.TryGetRelease(out var nextState))
|
|
TransitionStateInternal(nextState);
|
|
if (Enabled)
|
|
{
|
|
if (cancelUpdateStateThisFrame is false)
|
|
{
|
|
CurrentState?.OnStateUpdate(deltaTime);
|
|
}
|
|
cancelUpdateStateThisFrame = false;
|
|
}
|
|
|
|
}
|
|
|
|
public void DisposeState()
|
|
{
|
|
}
|
|
public void TransitionState<State>() where State : TState
|
|
{
|
|
var nextState = StateDictionary.GetOrCreate(typeof(State));
|
|
TransitionState(nextState);
|
|
}
|
|
public void TransitionState(TState newState)
|
|
{
|
|
if(transitionOnNextFrame)
|
|
_nextState.Release(newState);
|
|
else
|
|
{
|
|
TransitionStateInternal(newState);
|
|
cancelUpdateStateThisFrame = true;
|
|
}
|
|
}
|
|
private void TransitionStateInternal(TState newState)
|
|
{
|
|
if (Equals(newState,CurrentState)) return;
|
|
|
|
var oldState = CurrentState;
|
|
if (oldState is not null)
|
|
{
|
|
oldState.OnStateExit(oldState, newState);
|
|
oldState.Enabled = false;
|
|
}
|
|
|
|
_currentStateName = newState is not null ? newState.GetType().Name : "null";
|
|
if (debug)
|
|
{
|
|
BIT4Log.Log<MonoStateMachine<TState>>($"TransitionState from {_currentStateName} to {_currentStateName}");
|
|
}
|
|
CurrentState = newState;
|
|
|
|
if (newState is not null)
|
|
{
|
|
newState.Enabled = true;
|
|
newState.OnStateEntry(oldState);
|
|
}
|
|
OnStateChanged?.Invoke(oldState, newState);
|
|
}
|
|
public virtual void Register(TState newState)=>StateMachineUtils.Register(this,newState);
|
|
public virtual void UnRegister(TState newState)=>StateMachineUtils.UnRegister(this,newState);
|
|
public void InvokeOnStateRegistered(TState state)
|
|
{
|
|
OnStateRegistered?.Invoke(state);
|
|
}
|
|
|
|
public void InvokeOnStateUnRegistered(TState state)
|
|
{
|
|
OnStateUnRegistered?.Invoke(state);
|
|
}
|
|
}
|
|
|
|
} |