A lightweight Redux implementation for Unity projects, providing predictable state management for your game applications.
This Unity Redux library brings the power of Redux state management to Unity, allowing you to manage your game state in a predictable and maintainable way. Built with C# and integrated with R3 (Reactive Extensions) for reactive programming capabilities.
- Predictable State Management: Centralized state management following Redux principles
- Type-Safe Actions: Strongly typed actions using C# structs
- Reactive Programming: Built-in observables using R3 for state changes
- Unity Integration: Seamless integration with Unity's MonoBehaviour lifecycle
- Immutable State Updates: Ensures state consistency through reducer functions
- Install R3 using NuGetForUnity
- Open Package Manager window (Window | Package Manager)
- Click
+
button on the upper-left of a window, and select "Add package from git URL..." - Enter the following URL and click
Add
button
https://github.com/singh-ps/unity-redux.git?path=/Assets/Redux
NOTE: To install a concrete version you can specify the version by prepending #v{version} e.g.
#v1.0.0
. For more see Unity UPM Documentation.
public class GameState
{
public int Score { get; set; }
public int Health { get; set; }
public GameState()
{
Score = 0;
Health = 100;
}
public GameState(GameState other)
{
Score = other.Score;
Health = other.Health;
}
}
public readonly struct UpdateScoreAction
{
public readonly int Score;
public UpdateScoreAction(int score)
{
Score = score;
}
}
public readonly struct IncreaseHealthAction
{
public readonly int Amount;
public IncreaseHealthAction(int amount)
{
Amount = amount;
}
}
public static class GameReducers
{
public static GameState UpdateScoreReducer(GameState state, UpdateScoreAction action)
{
return new GameState(state)
{
Score = action.Score
};
}
public static GameState IncreaseHealthReducer(GameState state, IncreaseHealthAction action)
{
return new GameState(state)
{
Health = state.Health + action.Amount
};
}
}
public class GameStateStore : Store<GameState>
{
public GameStateStore() : base(new GameState())
{
}
protected override IReadOnlyDictionary<Type, Delegate> BuildReducers()
{
return new Dictionary<Type, Delegate>
{
{typeof(UpdateScoreAction), new Func<GameState, UpdateScoreAction, GameState>(GameReducers.UpdateScoreReducer)},
{typeof(IncreaseHealthAction), new Func<GameState, IncreaseHealthAction, GameState>(GameReducers.IncreaseHealthReducer)}
};
}
}
public class GameManager : MonoBehaviour
{
private readonly GameStateStore store = new();
private void Start()
{
// Subscribe to state changes
store.StateObservable.Subscribe(state =>
{
Debug.Log($"Score: {state.Score}, Health: {state.Health}");
});
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// Dispatch actions
store.Dispatch(new UpdateScoreAction(100));
store.Dispatch(new IncreaseHealthAction(10));
}
}
private void OnDestroy()
{
store.Dispose();
}
}
The central store that holds your application state and manages state updates through reducers.
CurrentState
: Get the current state valueStateObservable
: Observable stream of state changesDispatch<TAction>()
: Dispatch actions to update stateDispose()
: Clean up resources
Internal state container that wraps your state with R3's BehaviorSubject for reactive capabilities.
Define actions as readonly structs to ensure immutability and type safety.
Pure functions that take the current state and an action, returning a new state.
- Unity 2021.3+ (recommended)
- NuGetForUnity: For package management
- R3: For reactive programming support
Check out the complete example in Assets/Redux/Scripts/Examples/GameStateExample.cs
for a full implementation demonstrating:
- State definition
- Action creation
- Reducer implementation
- Store setup
- Unity integration
- Keep reducers pure: No side effects, always return new state objects
- Use readonly structs for actions: Ensures immutability
- Subscribe to state changes in Start(): Avoid memory leaks
- Always dispose stores: Call
Dispose()
inOnDestroy()
- Keep state immutable: Create new state objects instead of modifying existing ones
This project is licensed under the terms specified in the LICENSE file.
Contributions are welcome! Please feel free to submit issues and pull requests.