modesttree / Zenject

Dependency Injection Framework for Unity3D
MIT License
2.47k stars 273 forks source link

Passing data to prefab created by factory, using game object context #241

Open novalain opened 3 years ago

novalain commented 3 years ago

Describe the bug When using PrefabFactory or InstantiatePrefabForComponent through a custom factory, the framework implies that additional data can be passed to the facade/installer. However, if the object contains a game object context, Zenject failes to resolve the passed parameters.

To Reproduce

  1. Make a binding like Container.BindFactory<UnityEngine.Object, float, MyFacade, MyFacade.Factory>().FromFactory<PrefabFactory<float, MyFacade>>();
  2. Pass the data on creation myFactory.Create(prefab, 2f)
  3. Zenject fails to resolve the float if the given prefab has a game object context attached.

Steps to reproduce the behavior:

Expected behavior Data can be passed dynamically to prefab factories or custom factories that get a prefab at run time.

Extenject and Unity info (please complete the following information):

Additional context Noticed that doing the binding like:

Container.BindFactory<float, MyFacade, MyFacade.Factory>().FromSubContainerResolve().ByNewContextPrefab(...)

makes it work. However in our case it's not good enough, as we want to pass the prefab (and the data) along in run time.

nipunasudha commented 2 years ago

Hey any solution to this issue? I have the exact same requirement

adrianyip-1222 commented 2 years ago

Describe the bug When using PrefabFactory or InstantiatePrefabForComponent through a custom factory, the framework implies that additional data can be passed to the facade/installer. However, if the object contains a game object context, Zenject failes to resolve the passed parameters.

To Reproduce

  1. Make a binding like Container.BindFactory<UnityEngine.Object, float, MyFacade, MyFacade.Factory>().FromFactory<PrefabFactory<float, MyFacade>>();
  2. Pass the data on creation myFactory.Create(prefab, 2f)
  3. Zenject fails to resolve the float if the given prefab has a game object context attached.

Steps to reproduce the behavior:

Expected behavior Data can be passed dynamically to prefab factories or custom factories that get a prefab at run time.

Extenject and Unity info (please complete the following information):

  • Zenject version: 9.2.0
  • Unity version: 2020.3.9f1
  • Project's scripting backend [e.g. Mono/IL2CPP] Editor

Additional context Noticed that doing the binding like:

Container.BindFactory<float, MyFacade, MyFacade.Factory>().FromSubContainerResolve().ByNewContextPrefab(...)

makes it work. However in our case it's not good enough, as we want to pass the prefab (and the data) along in run time.

+1 I have the same issue

lucid-dreamm commented 1 year ago

+1 I need exactly this feature, same problem.

SimonNordon4 commented 1 year ago

It's possible to pass data into a prefab's GameObjectContext via a factory using this code:

public GameObject facadePrefab

public override void InstallBindings()
{
    Container.BindFactory<TestData, Facade, Facade.Factory>()
        .FromSubContainerResolve()
        .ByNewPrefabInstaller<FacadeInstaller>(facadePrefab);
}

The FacadePrefab most have the following components attached to it:

The MonoInstaller must bind it's data in this way

[InjectOptional]private TestData data = new TestData();

public override void InstallBindings()
{
    Container.BindInstance(data)
}

When the facadePrefab is created via Facade.Factory.Create(myTestData), myTestData will be injected into the monoinstaller, and thus into the GameObjectContext.

This works perfectly fine for Factories, but no for MemoryPooled Factories. So far I haven't found a way to Re-inject a gameobject that is spawned via a MemoryPool.