mirror of
https://github.com/Bragin-Stepan/project-entity.git
synced 2026-03-05 07:41:10 +00:00
feat: add state machine
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
|
||||
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public interface IState
|
||||
{
|
||||
IReadOnlyEvent Entered { get; }
|
||||
IReadOnlyEvent Exited { get; }
|
||||
|
||||
void Enter();
|
||||
void Exit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aed062833c374a6c8f4f784616dad179
|
||||
timeCreated: 1772453453
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public interface IUpdatableState : IState
|
||||
{
|
||||
void Update(float deltaTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1ea582554484972bd37276974ad4434
|
||||
timeCreated: 1772453453
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public abstract class ParallelState<TState> : State where TState : class, IState
|
||||
{
|
||||
private List<TState> _states;
|
||||
|
||||
public ParallelState(params TState[] states)
|
||||
{
|
||||
_states = new List<TState>(states);
|
||||
}
|
||||
|
||||
protected IReadOnlyList<TState> States => _states;
|
||||
|
||||
public override void Enter()
|
||||
{
|
||||
base.Enter();
|
||||
|
||||
foreach (TState state in _states)
|
||||
state.Enter();
|
||||
}
|
||||
|
||||
public override void Exit()
|
||||
{
|
||||
base.Exit();
|
||||
|
||||
foreach (TState state in _states)
|
||||
state.Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3084d8be941e4eb89f019da66b818702
|
||||
timeCreated: 1772453453
|
||||
@@ -0,0 +1,18 @@
|
||||
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public abstract class State : IState
|
||||
{
|
||||
private ReactiveEvent _entered = new();
|
||||
private ReactiveEvent _exited = new();
|
||||
|
||||
public IReadOnlyEvent Entered => _entered;
|
||||
|
||||
public IReadOnlyEvent Exited => _exited;
|
||||
|
||||
public virtual void Enter() => _entered.Invoke();
|
||||
|
||||
public virtual void Exit() => _exited.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 975fa4387d1e4f37afb584f32071e4bc
|
||||
timeCreated: 1772453453
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using _Project.Develop.Runtime.Utilities.Conditions;
|
||||
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public abstract class StateMachine<TState> : State, IDisposable, IUpdatableState where TState : class, IState
|
||||
{
|
||||
private List<StateNode<TState>> _states = new();
|
||||
|
||||
private StateNode<TState> _currentState;
|
||||
|
||||
private bool _isRunning;
|
||||
|
||||
private List<IDisposable> _disposables;
|
||||
|
||||
protected StateMachine(List<IDisposable> disposables)
|
||||
{
|
||||
_disposables = new List<IDisposable>(disposables);
|
||||
}
|
||||
|
||||
protected TState CurrentState => _currentState.State;
|
||||
|
||||
public void AddState(TState state) => _states.Add(new StateNode<TState>(state));
|
||||
|
||||
public void AddTransition(TState fromState, TState toState, ICondition condition)
|
||||
{
|
||||
StateNode<TState> from = _states.First(stateNode => stateNode.State == fromState);
|
||||
StateNode<TState> to = _states.First(stateNode => stateNode.State == toState);
|
||||
|
||||
from.AddTransition(new StateTransition<TState>(to, condition));
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
if (_isRunning == false)
|
||||
return;
|
||||
|
||||
foreach (StateTransition<TState> transition in _currentState.Transitions)
|
||||
{
|
||||
if (transition.Condition.Evaluate())
|
||||
{
|
||||
SwitchState(transition.ToState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateLogic(deltaTime);
|
||||
}
|
||||
|
||||
protected virtual void UpdateLogic(float deltaTime) { }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_isRunning = false;
|
||||
|
||||
foreach (StateNode<TState> stateNode in _states)
|
||||
if (stateNode.State is IDisposable disposableState)
|
||||
disposableState.Dispose();
|
||||
|
||||
_states.Clear();
|
||||
|
||||
foreach (IDisposable disposable in _disposables)
|
||||
disposable.Dispose();
|
||||
|
||||
_disposables.Clear();
|
||||
}
|
||||
|
||||
public override void Enter()
|
||||
{
|
||||
base.Enter();
|
||||
|
||||
if (_currentState == null)
|
||||
SwitchState(_states[0]);
|
||||
|
||||
_isRunning = true;
|
||||
}
|
||||
|
||||
public override void Exit()
|
||||
{
|
||||
base.Exit();
|
||||
|
||||
_currentState?.State.Exit();
|
||||
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
private void SwitchState(StateNode<TState> nextState)
|
||||
{
|
||||
_currentState?.State.Exit();
|
||||
_currentState = nextState;
|
||||
_currentState.State.Enter();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 421f6f14fa064baaa737bea3684d473f
|
||||
timeCreated: 1772453453
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public class StateNode<TState> where TState : class, IState
|
||||
{
|
||||
private List<StateTransition<TState>> _transitions = new();
|
||||
|
||||
public StateNode(TState state)
|
||||
{
|
||||
State = state;
|
||||
}
|
||||
|
||||
public TState State { get; }
|
||||
|
||||
public IReadOnlyList<StateTransition<TState>> Transitions => _transitions;
|
||||
|
||||
public void AddTransition(StateTransition<TState> transition) => _transitions.Add(transition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dce697e6ac3b45b497e8e89c5ca258cc
|
||||
timeCreated: 1772453453
|
||||
@@ -0,0 +1,16 @@
|
||||
using _Project.Develop.Runtime.Utilities.Conditions;
|
||||
|
||||
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||
{
|
||||
public class StateTransition<TState> where TState : class, IState
|
||||
{
|
||||
public StateTransition(StateNode<TState> toState, ICondition condition)
|
||||
{
|
||||
ToState = toState;
|
||||
Condition = condition;
|
||||
}
|
||||
|
||||
public StateNode<TState> ToState { get; }
|
||||
public ICondition Condition { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07aef2e29c2643419ff17e32556da944
|
||||
timeCreated: 1772453453
|
||||
Reference in New Issue
Block a user