public class StateMachine<T> where T : MonoBehaviour { private readonly T _stateMachineController; private Command _currentState; public StateMachine (T stateMachineController) { this._stateMachineController = stateMachineController; } public TCommand ApplyState<TCommand> (params object[] args) where TCommand : CommandWithType<T> { if (_currentState != null) _currentState.Terminate (); _currentState = Command.ExecuteOn<TCommand> (_stateMachineController.gameObject, _stateMachineController, args); return _currentState as TCommand; } }
public class SceneController : StateMachineHolder { public StateMachine<SceneController> StateMachine { get; private set; } public SceneController () { StateMachine = new StateMachine<SceneController> (this); } private void Start() { StateMachine.ApplyState<InitializeState> (); } }
public class SceneState: CommandWithType<SceneController> { } class InitializeState : SceneState { protected override void OnStart (object[] args) { base.OnStart (args); //test UnityEngine.Debug.Log(string.Format("{0}", "Initialize state")); Controller.StateMachine.ApplyState<ReadyState> (); } } class ReadyState : SceneState { protected override void OnStart (object[] args) { base.OnStart (args); //test UnityEngine.Debug.Log(string.Format("{0}", "ready state")); } }
public class UpdateScoreCommand : SceneState { protected override void OnStart (object[] args) { base.OnStart (args); StartCoroutine (UpdateScore()); } private IEnumerator UpdateScore () { while (true) { if (!IsRunning) yield break; yield return new WaitForSeconds (1); Controller.Score++; } } }
class ReadyState : SceneState { private UpdateScoreCommand _updateScoreCommand; protected override void OnStart (object[] args) { base.OnStart (args); //test UnityEngine.Debug.Log(string.Format("{0}", "ready state")); _updateScoreCommand = Command.ExecuteOn<UpdateScoreCommand> (Controller.gameObject, Controller); } protected override void OnReleaseResources () { base.OnReleaseResources (); _updateScoreCommand.Terminate (); } }
public class StateMachine<T> where T : MonoBehaviour { private readonly T _stateMachineController; private Command _currentState; private List<CommandWithType<T>> _commands; public StateMachine (T stateMachineController) { this._stateMachineController = stateMachineController; _commands = new List<CommandWithType<T>> (); } public TCommand ApplyState<TCommand> (params object[] args) where TCommand : CommandWithType<T> { if (_currentState != null) _currentState.Terminate (true); StopAllCommands (); _currentState = Command.ExecuteOn<TCommand> (_stateMachineController.gameObject, _stateMachineController, args); return _currentState as TCommand; } public TCommand Execute<TCommand> (params object[] args) where TCommand : CommandWithType<T> { TCommand command = Command.ExecuteOn<TCommand> (_stateMachineController.gameObject, _stateMachineController, args); _commands.Add (command); return command as TCommand; } private void StopAllCommands() { for (int i = 0; i < _commands.Count; i++) { _commands [i].Terminate (); } } }
class ReadyState : SceneState { protected override void OnStart (object[] args) { base.OnStart (args); //test UnityEngine.Debug.Log(string.Format("{0}", "ready state")); Controller.StateMachine.Execute<UpdateScoreCommand> (); } }
public bool FinishResult { get; private set; } public static T ExecuteOn<T>(GameObject target, params object[] args) where T : Command { return ExecuteOn (typeof(T), target, args) as T; } public static Command ExecuteOn(Type type, GameObject target, params object[] args) { Command command = (Command)target.AddComponent (type); command._args = args; return command; } protected void FinishCommand(bool result = true) { if (!IsRunning) return; OnReleaseResources (); OnFinishCommand (); FinishResult = result; if (result) CallbackToken.FireSucceed (); else CallbackToken.FireFault (); Destroy (this, 1f); }
public sealed class CommandPair { public readonly Type TargetType; public readonly Type SuccesType; public readonly Type FaultType; public CommandPair (Type targetType, Type succesType, Type faultType) { this.TargetType = targetType; this.SuccesType = succesType; this.FaultType = faultType; } public CommandPair (Type targetType, Type succesType) { this.TargetType = targetType; this.SuccesType = succesType; this.FaultType = succesType; }
public sealed class CommandFlow { private List<CommandPair> _commandFlow; public CommandFlow () { this._commandFlow = new List<CommandPair>(); } public void AddCommandPair(CommandPair commandPair) { _commandFlow.Add (commandPair); } public Type GetNextCommand(Command currentCommand) { CommandPair nextPair = _commandFlow.FirstOrDefault (pair => pair.TargetType.Equals (currentCommand.GetType ())); if (nextPair == null) return null; if (currentCommand.FinishResult) return nextPair.SuccesType; return nextPair.FaultType; } }
public class StateMachine<T> where T : MonoBehaviour { private readonly T _stateMachineController; private readonly CommandFlow _commandFlow; private Command _currentState; private List<CommandWithType<T>> _commands; public StateMachine (T stateMachineController) { this._stateMachineController = stateMachineController; _commands = new List<CommandWithType<T>> (); } public StateMachine (T _stateMachineController, CommandFlow _commandFlow) { this._stateMachineController = _stateMachineController; this._commandFlow = _commandFlow; _commands = new List<CommandWithType<T>> (); } public TCommand ApplyState<TCommand> (params object[] args) where TCommand : CommandWithType<T> { return ApplyState (typeof(TCommand), args) as TCommand; } public Command ApplyState(Type type, params object[] args) { if (_currentState != null) _currentState.Terminate (true); StopAllCommands (); _currentState = Command.ExecuteOn (type ,_stateMachineController.gameObject, _stateMachineController, args); _currentState.CallbackToken.AddCallback (new Callback<Command>(OnStateFinished, OnStateFinished)); return _currentState; } private void OnStateFinished (Command command) { if (_commandFlow == null) return; Type nextCommand = _commandFlow.GetNextCommand (command); if (nextCommand != null) ApplyState (nextCommand); } public TCommand Execute<TCommand> (params object[] args) where TCommand : CommandWithType<T> { TCommand command = Command.ExecuteOn<TCommand> (_stateMachineController.gameObject, _stateMachineController, args); _commands.Add (command); return command as TCommand; } private void StopAllCommands() { for (int i = 0; i < _commands.Count; i++) { _commands [i].Terminate (); } } }
public class SceneController : StateMachineHolder { public int Score = 0; public StateMachine<SceneController> StateMachine { get; private set; } public SceneController () { CommandFlow commandFlow = new CommandFlow (); commandFlow.AddCommandPair (new CommandPair(typeof(InitializeState), typeof(ReadyState), typeof(OverState))); StateMachine = new StateMachine<SceneController> (this, commandFlow); } private void Start() { StateMachine.ApplyState<InitializeState> (); } } class InitializeState : SceneState { protected override void OnStart (object[] args) { base.OnStart (args); //test UnityEngine.Debug.Log(string.Format("{0}", "Initialize state")); FinishCommand (Random.Range (0, 100) < 50); } }
Source: https://habr.com/ru/post/281545/
All Articles