Modular architecture for Unity 3D #2: Scene Manager

In previous note I have described basic idea behind my modular architecture that I’m using in my projects. Framework described so far works perfectly with one scene setup. That is not completely true, it works perfectly if scenes that you will load are completely independent from one another. To deal with that I have implemented SceneManager class.

GameManager

I have added event to GameManager that will allow SceneManager to be notified about modules being registered.

public event Action<AModuleManager> ModuleInitialized = (module) => {};

private IEnumerator RegisterModuleRoutine()
{
  (...)
  asyncInstantiateHandle.Completed += delegate(AsyncOperationHandle<GameObject> handle)     
  {
    AModuleManager moduleManager = handle.Result.GetComponent<AModuleManager>();
    Type moduleManagerType = moduleManager.GetType();
    this._modulesReferences[moduleReference] = moduleManagerType;
    this._modules[moduleManagerType] = moduleManager;
    
    CheckDependencyRequests(moduleManagerType);

    moduleManager.Initialize(this);
    //NEW ADDITION
    ModuleInitialized.Invoke(moduleManager);

    this._logger.Log(LoggerLevel.Info,
    $"Module {moduleManagerType} successfully registered.",
    $"Registration Queue elements left: {this._moduleInitializationQueue.Count}",
    moduleManager.gameObject);
  };
}

AModuleManager

Module Manager received small update too. Virtual method for passing reference to the SceneManager.

public virtual void SetSceneDependencies(SceneManager sceneManager)
{}

SceneManager

Scene Manager provides basic functionality needed for handling additive scenes with their own modules. It can be inherited from to create more specialised implementation of the manager (i.e. providing spawn points in platformer)

public class SceneManager : CachedMonoBehaviour
{
  private GameManager _gameManager = null;
  private SceneLoader _sceneLoader = null;
  private AssetReference _sceneReference = null;
  [SerializeField]
  private List<AssetReference> _sceneModules = new List<AssetReference>();

  private void Awake()
  {
    this._gameManager = AppManager.Instance.GameManager;
    this._sceneLoader = this._gameManager.SceneLoader;
    this._gameManager.ModuleInitialized += PassDependenciesToModule;

    foreach(AssetReference moduleReference in this._sceneModules)
    {
      this._gameManager.RegisterModule(moduleReference);
    }

    PostInitializationRoutine();
  }
  
  public void UnloadScene()
  {
    foreach(AssetReference moduleReference in this._sceneModules)
    {
      this._gameManager.UnregisterModule(moduleReference);
    }
    this._gameManager.ModuleInitialized -= PassDependenciesToModule;
    this._sceneLoader.UnloadScene(this._sceneReference);
  }

  protected virtual IEnumerator PostInitializationRoutine()
  {
    yield return null;
  }

  private void PassDependenciesToModule(AModuleManager moduleManager)
  {
    moduleManager.SetSceneDependencies(this);
  }
}