ssannandeji / Zenject-2019

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

Add hooks before injecting prefab etc #396

Open ghost opened 6 years ago

ghost commented 6 years ago

It may be useful to develop moddable games.

For example, with such hooks we can add additional MonoInstallers to some GameObjectContext before it was processed during spawning prefab via Factory.

svermeulen commented 6 years ago

Added event handlers to GameObjectContext, ProjectContext, and SceneContext. So what you can do is either set AutoRun to false, add event handlers, then start it manually, or add event handlers in an Awake for an object that has a script execution order earlier than the context

ghost commented 6 years ago

How can I now add additional MonoInstaller to instantiated prefab by Zenject?

I implemented such dirty solution for now in my project

    public class DiContainer : IInstantiator
    {
        public static event Action<GameObject> BeforeInjectPrefab;

        ...

        public GameObject InstantiatePrefab(UnityEngine.Object prefab, GameObjectCreationParameters gameObjectBindInfo)
        {
            FlushBindings();

            bool shouldMakeActive;
            var gameObj = CreateAndParentPrefab(prefab, gameObjectBindInfo, null, out shouldMakeActive);

            BeforeInjectPrefab?.Invoke(gameObj);

        ...

and then I can access every instantiated prefab BEFORE injection to mix some other MonoInstaller.

DiContainer.BeforeInjectPrefab += instantiatedGo =>
{
    if (instantiatedGo.name.StartsWith("StoryUiNode"))
    {
        new HierarchyMerger().Merge(StoryMergeablePrefab, instantiatedGo);
    }
};

How can I do smth like this with newly introduced events?

svermeulen commented 6 years ago

Can you set AutoRun to false on the GameObjectContext, then call DiContainer.InstantiatePrefab, then add your installers, then call GameObjectContext.Run ?

ghost commented 6 years ago

Yep

But for me It means to move my whole project from Factories to manual instantiation to support modding via mixing prefabs before injection.

In this case I also need to introduce some event to catch that moment before instantiation any specific prefab that third-party developer want to mix into.

I will think more about it in a few hours.

ghost commented 6 years ago

I will continue to use my own DiContainer.BeforeInjectPrefab but I still think that somehow catch the moment between Instaniation and Injection will be very helpful feature.

svermeulen commented 6 years ago

Would something like https://github.com/modesttree/Zenject/issues/499 solve this or do you want a global callback?