I have a "Main" scene consisting of a softozor
game object which is controlled by the player. It's a flappy dinosaur. As a child of that softozor
game object, I have setup another game object, Installer
, consisting of a Transform component and a PlayerInstaller (Script)
component:
The PlayerInstaller
installs everything necessary for my player's logic. Finally, in the softozor
game object, I have added a Game Object Context (Script)
where I register the PlayerInstaller
:
In addition to the softozor
game object, I have also defined a SceneContext
:
You'll notice that all installers lists are empty in that SceneContext
. However, without that SceneContext
registering nothing, the PlayerInstaller
is not triggered. Playing the game with that setup works perfectly well, i.e. the PlayerInstaller
is called and I can control my dinosaur to do whatever I want in my game.
So far, so good. Now, consider the following Scene Test:
public class PlayerTests : SceneTestFixture
{
[Inject]
private IPlayer _player;
[UnityTest]
public IEnumerator TestScene()
{
yield return LoadScene("Main");
_player.Flap();
yield return new WaitForSeconds(0.01f);
[...]
}
}
In that test, the _player
member variable is not injected with an object satisfying the IPlayer
contract. In fact, the PlayerInstaller.InstallBindings()
is not called.
If I, instead, get rid of the Game Object Context (Script)
component in my softozor
game object, and register the PlayerInstaller
in the SceneContext
:
then I can play the game too, as before, and my test is running, i.e. the PlayerInstaller.InstallBindings()
method is called during my Scene Test.
What is wrong with my first attempt where I register the PlayerInstaller
in the softozor
game object context?
I am working with
So you have two containers, the SceneContext
and a GameObjectContext
.
I think what happens here is that they both get installed, but your GameObjectContext
is not added to the SceneContext
-- it worked until the SceneContext
actually needed to know about the GameObjectContext
(which was the case in your scene test).
It's difficult to give more precise directions not knowing what is IPlayer
and what you expect to be injected there, but it makes sense that it's not injected in your SceneContext
, but only in your GameObjectContext
.
By putting the PlayerInstaller
in the SceneContext
's MonoInstallers list, you technically solved that problem, but that's clearly not what you want since it makes the sub-container useless and breaks any kind of separation you were going for.
Instead, you need to interface both contexts using a façade: Sub-containers and Facades: Using GameObjectContexts (the explanation consists of an example, so it doesn't make sense for me to quote parts of it, but it's detailed and helpful)