/unity-asyncstatemachine

Asynchronous Statemachine for Unity

Primary LanguageC#

AsyncStateMachine for Unity

Simple statemachine for Unity that allows asynchronous state transitions.

Dependencies

  • UniTask (tested with version 1.1.0)
  • make sure API compatibility level is set to .NET 4.x in the player settings

Example

A complete example project can be found in the branch unity-project of this repository.

using UnityEngine;
using UniRx.Async;
using AsyncStateMachine;

public class SimpleExample : MonoBehaviour
{

    enum State
    {
        STATE_1,
        STATE_2,
        STATE_3,
        STATE_4
    };

    Statemachine<State> statemachine = new Statemachine<State>();

    // State1: using UniTasks
    async UniTask State1_Enter(State from)
    {
        Debug.Log("Entering State 1");
        await UniTask.Delay(2000);
        Debug.Log("Done Entering State 1");
    }

    async UniTask State1_Exit(State to)
    {
        Debug.Log("Exiting State 1");
        await UniTask.Delay(2000);
        Debug.Log("Done Exiting State 1");
    }

    // State2: using synchrounous callback functions
    void State2_Enter(State from)
    {
        Debug.Log("Entering State 2");
        Debug.Log("Entered State 2");
    }

    void State2_Exit(State to)
    {
        Debug.Log("Exiting State 2");
        Debug.Log("Exited State 2");
    }

    // State 3: using IState interface and thus UniTasks
    class State3 : IState<State>
    {
        public async UniTask OnEnter(State from)
        {
            Debug.Log("Entering State 3");
            await UniTask.Delay(2000);
            Debug.Log("Done Entering State 3");
        }

        public async UniTask OnExit(State to)
        {
            Debug.Log("Exiting State 3");
            await UniTask.Delay(2000);
            Debug.Log("Done Exiting State 3");
        }
    }

    // State 4: using ISyncState interface
    class State4 : ISyncState<State>
    {
        public void OnEnter(State from)
        {
            Debug.Log("Entering State 4");
            Debug.Log("Done Entering State 4");
        }

        public void OnExit(State to)
        {
            Debug.Log("Exiting State 4");
            Debug.Log("Done Exiting State 4");
        }
    }

    void Start()
    {
        // setting up the statemachine
        statemachine.AddStateWithTasks(State.STATE_1, State1_Enter, State1_Exit);
        statemachine.AddStateWithCallbacks(State.STATE_2, State2_Enter, State2_Exit);
        statemachine.AddState(State.STATE_3, new State3());
        statemachine.AddSyncState(State.STATE_4, new State4());

        // setting up optional event callbacks
        statemachine.OnStateEntering += (trans => Debug.Log("Statemachine: Entering state " + trans.To));
        statemachine.OnStateEntered += (trans => Debug.Log("Statemachine: Entered state " + trans.To));
        statemachine.OnStateExiting += (trans => Debug.Log("Statemachine: Exiting state " + trans.From));
        statemachine.OnStateExited += (trans => Debug.Log("Statemachine: Exited state " + trans.From));

        // initial transition, we fire and forget here using a discard _
        _ = statemachine.TransitionToState(State.STATE_1);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            _ = statemachine.TransitionToState(State.STATE_1);
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            _ = statemachine.TransitionToState(State.STATE_2);
        }
        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            _ = statemachine.TransitionToState(State.STATE_3);
        }
        if (Input.GetKeyDown(KeyCode.Alpha4))
        {
            _ = statemachine.TransitionToState(State.STATE_4);
        }

    }
}