SkillAgentSearch skills...

Reflex

Minimal dependency injection framework for Unity

Install / Use

/learn @gustavopsantos/Reflex

README

<div align=center> <p align="center"> <img src="graphics\logo.png" width="250"> </p>

Blazing fast, minimal but complete dependency injection library for <a href="https://unity.com/">Unity</a>

Reflex is an Dependency Injection framework for Unity. Making your classes independent of its dependencies, granting better separation of concerns. It achieves that by decoupling the usage of an object from its creation. This helps you to follow SOLID’s dependency inversion and single responsibility principles. Making your project more readable, testable and scalable.

Discord License: MIT Tests PullRequests Releases OpenUPM Unity

</div>
<details> <summary>📌 Table Of Contents</summary> </details>

👀 Overview

  • Fast: up to 414% faster than VContainer, up to 800% faster than Zenject.
  • GC Friendly: up to 28% less allocations than VContainer, up to 921% less allocations than Zenject.
  • AOT Support: Basically there's no runtime Emit, so it works fine on IL2CPP builds. <sup>[*]</sup>
  • Contract Table: Allows usages of APIs like container.All<IDisposable>
  • Immutable Container: Performant thread safety free of lock plus predictable behavior.
  • Source Generated: Implements modern Roslyn source generator to minimize reflection usage and speed up injection.

Compatible with the following platforms:

  • iOS
  • Android
  • Windows/Mac/Linux
  • PS4/PS5
  • Xbox One/S/X and Xbox Series X/S
  • WebGL

💾 Installation

You can install Reflex using any of the following methods:

Unity Package Manager

https://github.com/gustavopsantos/reflex.git?path=/Assets/Reflex/#14.3.0
  1. In Unity, open WindowPackage Manager.
  2. Press the + button, choose "Add package from git URL..."
  3. Enter url above and press Add.

Open Unity Package Manager

openupm install com.gustavopsantos.reflex

Unity Package

  1. Download the .unitypackage from releases page.
  2. Import Reflex.X.X.X.unitypackage

🚀 Getting Started

  1. Install Reflex
  2. Create RootInstaller.cs with
using Reflex.Core;
using UnityEngine;

public class RootInstaller : MonoBehaviour, IInstaller
{
    public void InstallBindings(ContainerBuilder builder)
    {
        builder.RegisterValue("Hello"); // Note that values are always registered as singletons
    }
}
  1. In unity project window
  2. Right click over any folder, Create → Reflex → RootScope. Since RootScope is strongly referenced by ReflexSettings, you can create it anywhere, it does not need to be inside Resources folder.
  3. Select RootScope you just created
  4. Add RootInstaller.cs as a component
  5. Create directory Assets/Resources
  6. Right click over Resources folder, Create → Reflex → Settings. ReflexSettings should always be created directly inside Resources folder, without any subfolder.
  7. Select ReflexSettings ScriptableObject and add the RootScope prefab to the RootScopes list
  8. Create new scene Greet
  9. Add Greet to Build SettingsScenes In Build
  10. Create Greeter.cs with
using UnityEngine;
using System.Collections.Generic;
using Reflex.Attributes;

public class Greeter : MonoBehaviour
{
    [Inject] private readonly IEnumerable<string> _strings;

    private void Start()
    {
        Debug.Log(string.Join(" ", _strings));
    }
}
  1. Add Greeter.cs to any gameobject in Greet scene
  2. Inside Greet scene, create a scene scope, Right Click on Hierarchy > Reflex > SceneScope.
  3. Create GreetInstaller.cs with
using Reflex.Core;
using UnityEngine;

public class GreetInstaller : MonoBehaviour, IInstaller
{
    public void InstallBindings(ContainerBuilder builder)
    {
        builder.RegisterValue("World"); // Note that values are always registered as singletons
    }
}
  1. Add GreetInstaller.cs to the SceneScope you created on step 14
  2. Create new scene Boot
  3. Add Boot to Build SettingsScenes In Build
  4. Create Loader.cs with
using Reflex.Core;
using UnityEngine;

public class Loader : MonoBehaviour
{
    private void Start()
    {
        void InstallExtra(UnityEngine.SceneManagement.Scene scene, ContainerBuilder builder)
        {
            builder.RegisterValue("of Developers");
        }
        
        // This way you can access ContainerBuilder of the scene that is currently building
        ContainerScope.OnSceneContainerBuilding += InstallExtra;

        // If you are loading scenes without addressables
        UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("Greet").completed += operation =>
        {
            ContainerScope.OnSceneContainerBuilding -= InstallExtra;
        };

        // If you are loading scenes with addressables
        UnityEngine.AddressableAssets.Addressables.LoadSceneAsync("Greet").Completed += operation =>
        {
            ContainerScope.OnSceneContainerBuilding -= InstallExtra;
        };
    }
}
  1. Add Loader.cs to any gameobject at Boot scene
  2. Thats it, hit play from Boot scene
  3. When Greet scene is loaded, there should be 3 instances implementing string contract
  4. So when Greeter.Start is called, you should see the following log in the unity console: Hello World of Developers

🎬 Execution Order

<p align="center"> <img src="graphics/execution-order.png" /> </p>

🎯 Injection Strategy

As of version 8.0.0 Reflex has stopped automatically managing dependency injection for any scene.

If you plan on using dependency injection in one of your scenes, add a game object somewhere in the hierarchy with a ContainerScope component attached. You can still manage shared dependencies using Root Container or utilize this Scene Containers for limited access. This component must be present at scene load time.

This allows users to consume injected dependencies on callbacks such as Awake and OnEnable while giving more granular control over which scene should be injected or not.


🌱 Container Hierarchy

Default Behaviour

Reflex's default strategy for creating containers involves initially generating a root container. For each newly loaded scene, an additional container is created, which always inherits from the root container. This container hierarchy mirrors the flat hierarchy of Unity scenes. You can see how the structure looks like below:

graph
RootContainer --> BootScene
RootContainer --> LobbyScene
RootContainer --> GameScene
RootContainer --> GameModeTwoScene

Override scene container parent

To do this or whatever else you want with scene ContainerBuilder you can access it with SceneScope.OnSceneContainerBuilding like we show in Loader.cs in "Getting Started" section.

// here we take boot scene container just for an example, you can use any container you need
var bootSceneContainer = gameObject.scene.GetSceneContainer();
void OverrideParent(Scene scene, ContainerBuilder builder) => builder.SetParent(bootSceneContainer);
ContainerScope.OnSceneContainerBuilding += OverrideParent;

// If you are loading scenes without addressables
SceneManager.LoadSceneAsync("Lobby", LoadSceneMode.Additive).completed += operation =>
{
    ContainerScope.OnSceneContainerBuilding -= OverrideParent;
};

// If you are loading scenes with addressables
Addressables.LoadSceneAsync("Lobby", LoadSceneMode.Additive).Completed += operation =>
{
    ContainerScope.OnSceneContainerBuilding -= OverrideParent;
};

By utilizing this API, you can create hierarchical structures such as the one shown below:

graph
RootContainer-->BootScene
BootScene-->LobbyScene
  1. Please note that it is not possible to override the parent container for the initial scene loaded by Unity.
  2. Exercise caution when managing the scene lifecycle with this type of hierarchy. For example, unloading a parent scene before its child scenes can lead to unexpected behavior, as the parent container will be disposed while the child scenes are still active. As a general rule, always unload the scene hierarchy from the bottom up, starting with the child scenes and progressing to the pa
View on GitHub
GitHub Stars1.5k
CategoryDevelopment
Updated1d ago
Forks104

Languages

C#

Security Score

100/100

Audited on Mar 27, 2026

No findings