# VContainer Usage

All scenes after <mark style="color:green;">**\_Loader**</mark> must have script that inherited from SceneLifetimeScope.cs and represents as object in scene hierarchy (recomended to replace it on top of scene hierarchy).

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2F1CczJ7G0zoEGcpSHRyHi%2Fimage.png?alt=media&#x26;token=a571117d-0053-4d5e-acb0-b6b9af16f219" alt=""><figcaption><p>How it looks in Gameplay Scope</p></figcaption></figure>

Below example how you can register objects in scene. I prefer to use lifetime scope as scene controller, so in Start() it will run game systems (when all have target references):

```csharp
public class GameplayLifetimeScope : SceneLifetimeScope
{
    [Header("Items")]
    [SerializeField] private LibraryItemSettingsSO _itemsLibrary;

    [Header("Scene references")]
    [SerializeField] private Player _player;
    [SerializeField] private CameraFollower _cameraFollower;

    protected override void Configure(IContainerBuilder builder)
    {
        base.Configure(builder);
        
        // here we need to register all that will be used across scripts in scene
        // basicaly put all top systems and main objects which need for other scripts
        builder.RegisterComponent(_cameraFollower);
        builder.RegisterComponent(_player);
        
        var UI = UIManager.instance;
        builder.RegisterComponent(UI.GetCanvas<GameCanvasUI>());
        builder.RegisterComponent(UI.GetCanvas<InteractPopup>());
        builder.RegisterComponent(UI.GetCanvas<QuestsUI>());
        
        builder.RegisterComponent(CashManager.Instance);
        builder.RegisterComponent(PoolManager.instance);

        builder.RegisterComponent(_itemsLibrary);
        // this line below will create ItemsFactory (not monobehaviour)
        builder.Register<ItemsFactory>(Lifetime.Singleton).WithParameter(transform);
    }

    private void Start() {
        // start scene systems, gameplay logic 
        // all registered objects will already 
        // have references that we have registered in Configure() above
        var itemFactory = Container.Resolve<ItemsFactory>();
        itemFactory.SetupSceneItems(_sceneItems);

        _player.OnStart();
    }
}
```

And how to handle references that we registered:

```csharp
public class ItemsFactory {
    public LibraryItemSettingsSO Library => _itemsLibrary;

    private IObjectResolver _container;
    private LibraryItemSettingsSO _itemsLibrary;
    private PoolManager _pool;
    private Transform _sceneTransform;

    // Here is magic that VContainer does 
    // (injects registered objects that we did in LifetimeScope above)
    // Use [Inject] for constuctor or method always so we know that this ->
    // -> will be called by VContainer after Configure call before Awake()
    //
    // Make attention that we also added IObjectResolver that is needed to ->
    // -> inject dependencies for runtime created objects!
    [Inject]
    public ItemsFactory(IObjectResolver container, LibraryItemSettingsSO itemsLibrary, 
                        PoolManager pool, Transform sceneTransform) {
        _pool = pool;
        _container = container;
        _itemsLibrary = itemsLibrary;
        _sceneTransform = sceneTransform;
    }

    private GameObject GetInstance(ItemSettingsSO config) {
        GameObject instance;

        if (config.PoolSize > 0) {
            _pool.CreateScenePool(config.Prefab, config.PoolSize, _sceneTransform,
                                  autoFillCount: config.AutoFillCount);

            instance = _pool.ReuseGameObjectScenePool(config.Prefab);
        }
        else {
            instance = GameObject.Instantiate(config.Prefab);
        }

        // To inject use IInject interface with MonoBehaviour, so we can mark ->
        // -> object that it need inject and use here and in other similar cases
        if (instance.TryGetComponent(out IInject injectObject) && injectObject.NeedInject) {
            _container.Inject(injectObject);
        }

        return instance;
    }
}
```

For MonoBehaviour use \[<mark style="color:orange;">**Inject**</mark>] with method *<mark style="color:purple;">**Init()**</mark>* (name can be different, but for consistency recomended Init):

```csharp
public class Spawner : MonoBehaviour { .. }

// inside of Spawner class:
[Inject]
public void Init(ItemsFactory itemsFactory) {
    _itemsFactory = itemsFactory;
}
```

Conclusion:

1. Register references in <mark style="color:green;">**SceneLifetimeScope**</mark> *(inherit from)*, dependencies for registered objects injected automaticaly.
2. Use \[<mark style="color:orange;">**Inject**</mark>] attribute in classes and add arguments to method which is references that you want to get.&#x20;
3. To inject references for runtime created objects get IObjectResolver in \[Inject] constructor/method and inject after creation. Use IInject interface to mark injectable objects and check do they need inject (pool case).

[VContainer documentation](https://vcontainer.hadashikick.jp/) for more information.
