ssannandeji / Zenject-2019

Dependency Injection Framework for Unity3D
MIT License
2.53k stars 363 forks source link

Inject running on disabled gameobjects #588

Open MarcusChamberlain opened 5 years ago

MarcusChamberlain commented 5 years ago

I have a MonoBehaviour being created using the "FromComponentInNewPrefab" method which takes one parameter:

EnemyInstaller.cs:
Container.BindFactory<int, Enemy, Enemy.Factory>().FromComponentInNewPrefab(_settings.EnemyPrefab);

Then in the Enemy.cs file (the MonoBehaviour class):

 [Inject]
        public void Construct(int health)
        {
            this.health = health;
        }

        public class Factory : PlaceholderFactory<int, Enemy>
        {

        }

When I added the parameter to the factory, I started getting an error when validating/running the scene. It turned out to be because I have the prefab in the scene, however the prefab is disabled. If I remove it completely the scene works fine.

The workaround is to drag the prefab into the scene, makes some changes, save, delete the prefab, run the scene, add it back to the scene, rinse repeat. It works but it's clunky not being able to leave the prefab disabled in the scene while developing it.

I assume this is the intended behavior since Zenject needs to run on disabled gameobjects before Awake/Start is called and it can't tell the difference between a gameobject it made and one I left in the scene. In that case, is there anything I should be doing with the factory parameter to allow this? Maybe an overload somewhere with an empty constructor or marking something as optional?

svermeulen commented 5 years ago

This is intended behaviour but we could maybe add a setting for this that would change zenject to not inject on disabled game objects. It's a bit weird though because you couldn't enable it later since it would never get injected after it missed its chance. So really it would only be useful for this one use case you describe where you have a disabled prefab in the scene and never intend to enable it.

Another option is to mark all the inject parameters as optional.

FlorianAuer commented 5 years ago

I'm having the same issue in a more business-like environment. The backend gets initialised within the constructor, but needs to wait after user authenticates himself. It's possible to decouple initialisation with constructor, but when I'm using lazy DI, I expect that also the constructor is run when the c#-object is instantiated.