BITKit/Packages/Runtime~/Unity/Scripts/StateMachine/MonoStateMachine.cs

92 lines
2.7 KiB
C#

using System;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
#endif
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.StateMachine
{
[Serializable]
public abstract class MonoStateMachine
{
#if UNITY_EDITOR
public abstract IState CurrentStateAsIState { get; }
#endif
}
[Serializable]
public class MonoStateMachine<TState> :MonoStateMachine , IStateMachine<TState>, IMonoProxy 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;
[SerializeReference, SubclassSelector] public List<TState> states = new();
[SerializeField,ReadOnly] private string _currentStateName;
public IDictionary<Type, TState> StateDictionary { get; } = new Dictionary<Type, TState>();
private bool _enabled;
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()
{
if (Enabled)
CurrentState?.OnStateUpdate();
}
public void DisposeState()
{
}
public void TransitionState<State>() where State : TState
{
var nextState = StateDictionary.GetOrCreate(typeof(State));
TransitionState(nextState);
}
public void TransitionState(TState newState)
{
if (newState.Equals(CurrentState)) return;
var oldState = CurrentState;
if (oldState is not null)
{
oldState.OnStateExit(oldState, newState);
oldState.Enabled = false;
}
newState.OnStateEntry(oldState);
CurrentState = newState;
OnStateChanged?.Invoke(oldState, newState);
_currentStateName = newState.GetType().Name;
newState.Enabled = true;
}
public override IState CurrentStateAsIState => CurrentState;
}
}