State machine makes managing states easy, it is widely used in many games and apps. However, there are not many state machines that designed with front-end in mind.
Often, integrating multiple states with UI transition can be a huge hassle and needs extra code to make simple transitions working with states. RxStateMachine is designed with "front end first" and "Reactive" in mind.
RxStatemachine is built upon thefuntastic's finite state machine.
Basic structure is mostly same but the core logic is implemented with Unirx (Reactive Extension for Unity)
Thanks to thefuntastic and neuecc for amazing statemachine and unirx!
- Safe
- OverWrite
- Blend
- Support multiple statemachine instances
- Support Transition as routine or single call
- Notifies transition progress
- State Transition can be canceled
- no co-routine used, more reliable functionality
An example project is included (Unity 2017.3) to show the RxStateMachine in action. To use the state machine you need a few simple steps
using Bebimbop.Utilities.StateMachine;
public class MyStateMachineClass : MonoBehaviour { }
public enum States
{
Init,
Play
}
public StateMachine<States> MyStateMachine;
MyStateMachine = StateMachine<States>.Initialize(this);
This is where all of the magic in the RxStateMachine happens: in the background, it inspects your MonoBehaviour (this
) and looks for any methods described by the convention shown below.
You can call this at any time, but generally Awake()
is a safe choice.
MyStateMachine.ChangeState(States.Init);
//for single frame transition
private void Init_Enter()
{
Debug.Log("Init done!");
}
//for transiton over time
//float t is between 0 ~ 1 (Start ~ end)
private void Play_Enter(float t)
{
//Ui transition so easy!
canvasGroup.alpha = t;
Debug.Log( "Entering State.. Progress " + t);
}
/* output
Entering State.. Progress 0
Entering State.. Progress 0.43975
...
Entering State.. Progress 0.9476
Entering State.. Progress 1*/
//OnCancel Method gets called when transtion interrupted
//by either calling ChangeState() with overwirte or CancelTranstion()
private void Play_OnCancle()
{
canvasGroup.alpha = 0;
}
void Play_Update()
{
Debug.Log("Game Playing");
}
void Play_Exit()
{
Debug.Log("Game Over");
}
Currently supported methods are:
Enter
EnterCancel
Exit
ExitCancel
Finally
FixedUpdate
Update
LateUpdate
These methods can be private or public. The methods themselves are all optional, so you only need to provide the ones you actually intend on using.
Enter/Exit routines are supported by simply adding float
parameter into Enter/Exit methods. This can be a great way to accommodate animations. Note: FixedUpdate
, Update
and LateUpdate
calls won't execute while an Enter or Exit routine is running.
Finally
is a special method guaranteed to be called after a state has exited. This is a good place to perform any hygiene operations such as resetting Uis or removing event listeners.
There is simple support for managing asynchronous state changes with long enter or long exit.
MyStateMachine.SetDuration(enterDuration = 0.5f, exitDuration = 0.5f)
The default duration for enter/exit is 0.5f but you can set it to any value as you need. by calling this method will set all transition to set duration.
MyStateMachine.SetMode(transition = StateTransition.Safe);
The default is StateTransition.Safe
. This will always allow the current state to finish both it's enter and exit functions before transitioning to any new states. by calling this method will set all transition to set mode.
MyStateMachine.SetMode(transition = StateTransition.Overwrite);
StateMahcine.Overwrite
will cancel any current transitions and invoke Cancel
methods (more detail explained in advance usage section), and call the next state immediately. This means any code which has yet to run in enter and exit routines will be skipped. If you need to ensure you end with a particular configuration, the finally function will always be called:
void MyCurrentState_Finally()
{
//Reset object to desired configuration
}
MyStateMachine.SetMode(transition = StateTransition.Blend);
StateMahcine.Blend
this will call/run the current state Exit
routine and the next state Enter
routine at the same time. this is useful when you need crossfade transition.
MyStateMachine.CancelTransition();
All transitions can be canceled by calling this method, and it will invoke the current EnterCancel
or ExitCancel
or both depends on how far you in the transition.
e.g) if you call CancleTransition()
beginning of exit routine, it will invoke ExitCancel
. if you call it after entering to new state's Enter routine, it will invoke both current state's ExitCancel
and new state's EnterCancel
methods.
UniRx, Reactive extension for Unity. latest source code(as of 02/13/18) already included in this repository, but if you want to get a newer vision, Download Unirx
To use RxStateMachine over multiple scripts is also simple. Here's basic example how to setup RxStateMachine in multiple scripts
in this example, we declare StateMachine in GameManager.cs and make GameManager as a singleton to call it from other scripts
<GameManager.cs>
public class GameManager : MonoBehaviour
{
public StateMachine<State> MainStateMachine;
private void Awake()
{
//initialize statemachine in Awake() to avoid Null error in other scripts
MainStateMachine = StateMachine<State>.Initialize(this);
}
//define state
public enum State
{
RED = 0,BLUE
}
//some singleton behaviour
private static GameManager instance = null;
public static GameManager Instance { ... }
}
<RedState.cs>
public class RedState : MonoBehaviour
{
private StateMachine<State> _mainStateMachine;
private void Start()
{
_mainStateMachine = GameManger.MainStateMachine;
//add RedState as subscriber to mainStateMachine.
_mainStateMachine.AddSubscriber(this);
}
//call backs
private void RED_Enter(float t) { }
private void RED_Exit(float t) { }
}
<BlueState.cs>
public class BlueState : MonoBehaviour
{
private StateMachine<State> _mainStateMachine;
private void Start()
{
_mainStateMachine = GameManger.MainStateMachine;
//add BlueState as subscriber to mainStateMachine.
_mainStateMachine.AddSubscriber(this);
}
//call backs
private void BLUE_Enter(float t) { }
private void BLUE_Exit(float t) { }
}
[TODO] add description with examples...
- ChangeState(T newState)
- ChangeState(T newState, StateTransition transition)
- ChangeState(T newState, StateTransition transition, float enterDuration, float exitDuration)
[TODO] add a description with examples...
- Cancel in Safe Mode
- Cancel in OverWrite Mode
- Cancel in Blend Mode
RxStateMachine support multiple instances of StateMachine.
Example Located Assests/DemoScenes/MultipleStateMachineExample.unity
This example demonstrates most functionalities on RxStateMachine Change Settings on the left side and see the difference between 3 transition modes and Test cancellation to see how it works in different modes
Example Located Assests/DemoScenes/StateMachineExample.unity