Course contentsShow
← Unity Game Development
Lesson 483 of 8287. Advanced Game ArchitectureFree lesson

Managing Service Lifetimes with Zenject or VContainer

Configure dependency containers to manage the lifecycle of game services, ensuring dependencies are correctly instantiated and disposed of during scene transitions.

In this lesson, you will learn how to configure dependency containers to ensure your game services are instantiated and cleaned up correctly as your player moves between scenes.

Understanding Service Lifetimes

In a growing game, some services (like a ScoreManager) need to exist for the entire application, while others (like an EnemySpawner) should only exist while a specific scene is loaded. If you don't manage these lifetimes, you’ll end up with "zombie" services consuming memory or trying to access destroyed objects, leading to those frustrating MissingReferenceExceptions.

Dependency Injection (DI) frameworks like Zenject or VContainer allow you to define the scope of a dependency. When you register a service, you decide whether it lives in the Global Scope (Project Context) or the Local Scope (Scene Context).

Configuring Scope

Imagine you have an AudioService that should persist everywhere. You would bind this in your ProjectContext:

// Inside your ProjectInstaller
public override void InstallBindings() {
    Container.BindInterfacesAndSelfTo<AudioService>().AsSingle();
}

By using AsSingle(), the container ensures that exactly one instance is created and shared globally. When you transition scenes, this instance remains untouched.

Conversely, if you have a LevelManager that should be destroyed when the scene ends, you bind it in the SceneContext:

// Inside your SceneInstaller
public override void InstallBindings() {
    Container.BindInterfacesAndSelfTo<LevelManager>().AsSingle();
}

Disposal and Cleanup

The beauty of DI containers is how they handle teardown. If your service implements System.IDisposable, the container will automatically call the Dispose() method when the scope (the scene) is destroyed. This is the perfect place to unsubscribe from your Event Bus or clear lists, ensuring no memory leaks occur.

When you bind using AsSingle(), the container acts as the "owner" of that object. It keeps a reference to it, preventing the Garbage Collector from claiming it as long as the context exists. When the context is unloaded, the reference is dropped, and the container handles the graceful cleanup of all managed services.

Key Takeaway: By binding services to the correct scope—Project for global persistence and Scene for transient logic—you ensure that dependencies are automatically instantiated and disposed of, keeping your memory usage clean and your references valid.