Install via UPM
Add to Unity Package Manager using this URL
https://www.pkglnk.dev/track/vsm2.git README
A visual editor for designing state machines in Unity
Currently still a work in progress and subject to breaking changes. Visual State Machine is a Unity package designed to simplify the creation and management of state machines in Unity projects. It provides a visual editor for designing state machines, making it easier to create complex behaviors without writing extensive code.
Installation
Add VSM2 to your Unity project via Package Manager:
- Open Window > Package Manager
- Click + > Add package from git URL
- Enter:
https://www.pkglnk.dev/track/vsm2.git
https://github.com/user-attachments/assets/61388bea-8bd4-4f92-9f12-c0f5768e1e8f
Features
- Visual Editor: Design state machines using a user-friendly graphical interface.
- Unity Integration: Seamlessly integrates with Unity, allowing for easy implementation in your game projects.
- Custom State Support: Create your own states to handle specific game behaviors.
- Transition Management: Easily manage transitions between states with intuitive controls.
Installation
To install Visual State Machine in your Unity project, follow these steps:
- Open Unity and navigate to the Package Manager.
- Click on the + button and select Add package from git URL...
- Enter the following URL:
https://github.com/PaulNonatomic/VisualStateMachineV2.gitand press Add.
Migration Steps to Version 0.9.0-beta
When upgrading to Visual State Machine V2 (VSM2) version 0.9.0-beta, follow these steps to ensure a seamless transition and maintain functionality within your Unity project:
- Commit Changes: Before starting the upgrade, ensure all your current work is committed to version control.
- Update the package: Change the package address in your projects Packages/manifest.json file to https://github.com/PaulNonatomic/VisualStateMachineV2.git#0.9.0-migration
- Run the migration tool: open Tools -> VSM2 -> Migrate to 0.9.0-beta
- Update the package again: Once the migration has completed update the package to the latest, currently 0.9.6-beta
Usage
- Create a State Machine Asset
- In the Project panel, right-click and select Create -> State Machine -> State Machine.
- In the Project panel, right-click and select Create -> State Machine -> State Machine.
- Add States
- Either right-click and select Add State or drag out from the Entry State.
https://github.com/user-attachments/assets/ff8fb491-fc7a-4658-8ee0-de0ddb2e8c0b
- State Selection Window
- The State Selection window appears listing all available states.
- States are grouped by namespace with the inbuilt states appearing at the top.
- The group of states nearest to the location of the state machine asset will open by default, but all states remain accessible.
- The State Selection window appears listing all available states.
- Create a Custom State
- Here's the built-in
DelayStateas an example: - Add a
Transitionattribute to an exposed eventActionin order for it to appear upon the state's node in the State Machine Editor. - Serialized and public properties are also exposed in the state's node in the State Machine Editor. Note fields should be populated with value types and assets, not scene types.
- Here's the built-in
[NodeWidth(width:190), NodeColor(NodeColor.Teal), NodeIcon(NodeIcon.Clock)]
public class DelayState : BaseDelayState
{
[Transition(frameDelay:0)]
public event Action OnComplete;
[NonSerialized]
private float _elapsedTime;
[Enter]
public override void OnEnter()
{
_elapsedTime = 0f;
}
public override void OnUpdate()
{
_elapsedTime += Time.deltaTime;
if (_elapsedTime < Duration) return;
OnComplete?.Invoke();
}
}
- Assign the State Machine
- Create a GameObject with a StateMachineController component and assign your new state machine asset to it.
- Create a GameObject with a StateMachineController component and assign your new state machine asset to it.
- Run the Application
- With the StateMachineController selected, you can see the state of your state machine within the State Machine Editor window.
Typed Transitions
Passing Data Between States Using Typed Transitions
To pass data between states in the Visual State Machine, you utilize transitions. Transitions are defined by public event Actions that are decorated with a TransitionAttribute [Transition]. Here's how you can effectively use typed transitions:
Defining Transitions with Parameters
Basic Transitions
- Use Action for transitions without parameters.
Typed Transitions
- Use Action
to pass data between states. Note: The package currently supports a maximum of one parameter per transition. Action<T1, T2> or more parameters are not supported at this time.
- Use Action
Example: Passing an Integer Between States
Defining the Transition in the Source State
public class SourceState : State
{
[Transition]
public event Action<int> OnTransitionWithInt;
public void TriggerTransition()
{
int valueToPass = 42;
OnTransitionWithInt?.Invoke(valueToPass);
}
[Enter]
public void OnEnter()
{
// Initialization logic
}
}
Receiving the Transition in the Target State
public class TargetState : State
{
[Enter]
public void OnEnterWithInt(int receivedValue)
{
Debug.Log($"Received value: {receivedValue}");
}
}
Important Notes:
- Single Parameter Limitation: Currently, only one parameter is supported per transition. Ensure that your transitions use Action
with a single type parameter. - Entry Method Naming Convention:
- It's recommended to name your entry methods as OnEnter followed by the type, for example, OnEnterWithInt(int value). This enhances clarity and consistency.
- It's recommended to name your entry methods as OnEnter followed by the type, for example, OnEnterWithInt(int value). This enhances clarity and consistency.
- [Enter] Attribute Requirement:
- All entry methods must be decorated with the [Enter] attribute.
- Breaking Change: In version 0.9.0-beta and above, the OnEnter method is no longer abstract but virtual. If you do not override it and decorate it with the [Enter] attribute, it will not be called.
- Visual Indicators in the Editor:
- Any method decorated with the [Enter] attribute will appear as an input port at the bottom left of your state's node in the Visual State Machine graph, displaying the parameter type.
- Transitions are listed on the bottom right of your state's node with the corresponding type description for typed transitions.
- Connection Rules:
- Typed output ports will only connect to matching typed input ports.
- Transitions without types will only connect to input ports without types.
- When dragging out from an output port, valid input ports will remain highlighted while invalid ports are greyed out.
- Troubleshooting:
- If your entry method does not appear in the state's input ports list:
- Ensure you've added the [Enter] attribute.
- Verify that you're only using one parameter in your Action
.
- If your entry method does not appear in the state's input ports list:
Example: Implementing Typed Transitions
Multiply State with Typed Transition
public class MultiplyState : State
{
[Transition]
public event Action<float> OnCompleteWithResult;
[SerializeField]
private float _multiplyBy = 2;
[Enter]
public void OnEnterWithFloat(float value)
{
var result = value * _multiplyBy;
OnCompleteWithResult?.Invoke(result);
}
}
Result State Receiving Typed Transition
public class ResultState : State
{
[Enter]
public void OnEnterWithResult(float result)
{
Debug.Log($"Received result: {result}");
}
}
By following this approach, you can effectively pass data between states in your Visual State Machine, enhancing the flexibility and functionality of your state-driven behaviors.
Loops with Jump Nodes
Add JumpOutState state and set it's Id. Then create a JumpInState with the corresponding Id to jump from one node to another.
https://github.com/user-attachments/assets/35715234-e532-464b-9031-4b7780efd3ef
Transition Delay
The process of transitioning between nodes originally incurred no delay at all but when wiring up a looping state machine it could cause a stack overflow. To prevent this a delay of 1 frame has been added to all transitions by default, but this can be configured on a per transition bases by passing a frameDelay value through the Transition attribute, but please use with caution as a frameDelay of 0 can cause a stack overflow.
Copy & Paste
The State Machine Editor supports copy and paste within and between state machines.
https://github.com/user-attachments/assets/09c1b644-c519-4bfd-8c29-4b0771d8d8b6
Shared Data
States have access to a shared data store
public class StateOne : State
{
[Transition] public event Action OnComplete;
[Enter]
public override void OnEnter()
{
SharedData.SetData("age", 42);
OnComplete?.Invoke();
}
}
public class StateTwo : State
{
[Transition] public event Action OnComplete;
[Enter]
public override void OnEnter()
{
var age = SharedData.GetData<int>("age");
Debug.Log($"StateTwo - Age:{age}");
OnComplete?.Invoke();
}
}
This same data store is exposed externally to the state machine through the StateMachineController.SharedData
License
VisualStateMachineV2 is licensed under the MIT license
Installs Over Time
Operating Systems
Top Countries
Git Versions
Embed Install Badge
Add an install count badge to your README
[](https://www.pkglnk.dev/pkg/vsm2)<a href="https://www.pkglnk.dev/pkg/vsm2"><img src="https://www.pkglnk.dev/badge/vsm2.svg?style=pkglnk" alt="pkglnk installs"></a>
VSM2 has been my most popular repo to date. It's a great tool but I've made great progress on it's successor VSM3 coming soon.