using System; using System.Collections.Generic; using Unity.VisualScripting; namespace NBC { public class Fsm { private FsmBaseState _currentState; private Dictionary> _states = new Dictionary>(); private Dictionary _stateType2Id = new Dictionary(); private bool _doDebugOutput; private TOwnerClass _owner; private string _description; public uint CurrentStateId => _currentState.StateId; public FsmBaseState CurrentState => _currentState; public Fsm(string description, TOwnerClass owner, bool debugOutput = false) { _description = description; _owner = owner; _doDebugOutput = debugOutput; } public void RegisterState() where T : FsmBaseState, new() { var type = typeof(T); if (_stateType2Id.ContainsKey(type)) { LogError("State {0} already registered", type); return; } T result = new T(); _stateType2Id[type] = result.StateId; _states[result.StateId] = result; result.Init(_owner, this); } public void Start() where T : FsmBaseState, new() { Log("start"); EnterState(typeof(T)); } public void EnterState(Type type, FsmBaseState sourceState = null) { if (_stateType2Id.TryGetValue(type, out var id)) { EnterState(id, sourceState); } } public void EnterState(uint stateId, FsmBaseState sourceState = null) { uint prevState = 0; FsmTransmit param = null; if (_currentState != null) { prevState = _currentState.StateId; param = _currentState.Params; _currentState.Exit(); } _currentState = _states[stateId]; _currentState.PrevState = prevState; if (param != null) { _currentState.Params.AddRange(param); param.Clear(); } if (sourceState != null) { _currentState.Transition(sourceState); } else { _currentState.Enter(); } } public void Update() { if (_currentState != null) { _currentState.PreUpdate(); var type = _currentState.Update(); if (type != 0) { _currentState.NextState = type; EnterState(type); } } } public void FixedUpdate() { if (_currentState != null) { var type = _currentState.FixedUpdate(); if (type != 0) { _currentState.NextState = type; EnterState(type); } } } public void LateUpdate() { if (_currentState != null) { var type = _currentState.LateUpdate(); if (type != 0) { _currentState.NextState = type; EnterState(type); } } } public void LogError(string textPattern, params object[] args) { } public void Log(string text) { if (!_doDebugOutput) { } } } }