Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Zenject: Dependency Injection Framework for Unity

Discussion in 'Assets and Asset Store' started by eventropy, Sep 19, 2013.

  1. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    https://github.com/modesttree/Zenject

    For anyone coming from a background using dependency injection frameworks, or anyone that is frustrated with the default offerings in Unity in terms of dependency management, feel free to use the above code!

    At some point we would like to put it up in the Asset Store but we are in the middle of crunch right now so can't really justify doing anything on it. Desperately requires more documentation BUT I wanted to at least put it out there early in case other people could benefit. Since, as far as I know there isn't really a dependency injection framework available currently.
     
    Last edited: Sep 19, 2013
  2. disturbing

    disturbing

    Joined:
    Dec 12, 2010
    Posts:
    127
  3. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    308
    Hello,

    Is it possible to use Zenject in an Integration Test?

    I have this script, and I always have fail.

    Thank you
    Code (CSharp):
    1. using Zenject;
    2.  
    3.  
    4. [IntegrationTest.DynamicTest("Vehicle Dynamics SimuZen Test Scene")]
    5. [IntegrationTest.Timeout(30)]
    6. public class VehicleIntegrationTest : MonoBehaviour {
    7.  
    8.     [Inject]
    9.     private IVehicleQuery vehicleQuery;
    10.  
    11.     [Inject]
    12.     private IVehicleModifier vehicleModifier;
    13.  
    14.     [PostInject]
    15.     private void Init()
    16.     {
    17.         NullDetect();
    18.     }
    19.  
    20.     // Use this for initialization
    21.     void Start ()
    22.     {
    23.         NullDetect();
    24.  
    25.     }
    26.  
    27.     private void NullDetect()
    28.     {
    29.  
    30.         if (vehicleQuery.IsNotNull() && vehicleModifier.IsNotNull())
    31.         {
    32.             Pass();
    33.         }
    34.         else
    35.         {
    36.             Fail();
    37.         }
    38.     }
    39.  
    40.     private void Pass()
    41.     {
    42.         IntegrationTest.Pass(gameObject);
    43.     }
    44.  
    45.     private void Fail()
    46.     {
    47.         IntegrationTest.Fail(gameObject);
    48.     }
    49.  
    50. }
    51.  
     
  4. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    Is this with Unity Test Tools? Sorry, I don't know enough about that package to be very helpful
     
  5. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    308
    Yes, is with Unity Test Tools. I have seen that Zenject has tools for Unit Testing but with Integration testing I am not able to use DI.

    Don't worry, thank you anyway ;)
     
  6. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    308
    Hello again,

    How could I get the instantiated gameObject by a ToSinglePrefab?
    Code (CSharp):
    1. Container.Bind<IFoo>().ToSinglePrefab(gameObjectPrefab)
    Thank you.
     
  7. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    After adding that line to an installer, you should be able to get it just by asking for it in a constructor parameter or in any field or property marked [Inject] that has type IFoo

    You can also get it by calling Container.Resolve<IFoo>() but it is not good practice to do it that way
     
    Maeslezo likes this.
  8. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    308
    Hello,

    I have question regarding factories.

    When I need to instantiate a prefab, I can use the factory pattern with Container.BindGameObjectFactory<Factory>(Prefab)

    But what about bundles? Or if I need to get the prefab from Resources.Load()?

    I think the solution is to solve the prefab in the installer and then use the factory as usual, but I'd rather prefer to solve this in the factory_client code.

    I attach an example for clarity.

    Thank you.

    Code (CSharp):
    1. public class VehicleInstaller : MonoInstaller
    2. {
    3.  
    4.     public override void InstallBindings()
    5.     {
    6.         ...
    7.  
    8.         Container.BindGameObjectFactory<FooMonoBehaviour.Factory>(/*EMPTY instead of prefab*/);
    9.  
    10.         ...
    11.     }
    12. }
    13.  
    14. public class FooMonoBehaviour : MonoBehaviour
    15. {
    16.     ...
    17.     [Inject]
    18.     FooMonoBehaviour.Factory factory;
    19.     ...
    20.     public void Method()
    21.     {
    22.         GameObject prefab = GetPrefabFromBundleBecauseOfThisConfig(config, someParameter);
    23.         GameObject instantiatedGameObject = factory.Create(prefab /* PREFAB AS PARAMETER*/);
    24.      
    25.         DoSomething(instantiatedGameObject);
    26.      
    27.     }
    28.     ...
    29.  
    30.     public class Factory : GameObjectFactory<GameObject>
    31.     {
    32.     }
    33. }
     
  9. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249

    If you are getting the prefab from resources, there are bind methods for that as well (eg: ToSinglePrefabResource, ToTransientPrefabResource). Or if you are getting the resource name / prefab at runtime, you can use a class called PrefabFactory like this:

    Code (csharp):
    1.  
    2.     public class FooMonoBehaviour : MonoBehaviour
    3.     {
    4.         public class Factory : PrefabFactory<FooMonoBehaviour>
    5.         {
    6.         }
    7.     }
    8.  
    9. ..
    10.  
    11.     Container.Bind<FooMonoBehaviour.Factory>().ToSingle();
    12.  
    Using PrefabFactory is better than instantiating the prefab directly because this will ensure that your classes are validated when running zenject validation.

    For asset bundles, you could load the prefab yourself and then call PrefabFactory as described above. You could also create a custom factory that loads the asset bundle asyncronously from web or file or whatever then creates a prefab for it, something like:

    Code (csharp):
    1.  
    2.     public class UrlFactory
    3.     {
    4.         string _url;
    5.  
    6.         public UrlFactory(string url)
    7.         {
    8.             _url = url;
    9.         }
    10.  
    11.         public IEnumerator<GameObject> Create()
    12.         {
    13.             ....
    14.         }
    15.     }
    16.  
     
    ouchz and Maeslezo like this.
  10. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    308
    Thank you eventropy for your answer. I hadn't uploaded zenject for while and I did not have PrefabFactory.

    I see it is the right way to do it. The problem I have now is that Prefab Factory signature is like this
    Code (CSharp):
    1. public class PrefabFactory<T> : IValidatable where T : Component
    , but what I need to instantiate are GameObjects, and GameObjects are not Component. I could do a workaround doing something like
    Code (CSharp):
    1. public class Factory : PrefabFactory<Transform>{ }
    , but I am not sure neither is a good practice nor it could work.

    Thank you.
     
  11. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    If you want to just create game objects and not any particular components, then you should probably just use DiContainer or IInstantiator directly by calling _container.InstantiatePrefab(MyGameObject);

    That might be the best solution for this case, especially since Zenject won't be able to 'validate' your prefabs anyway without knowing what component class to validate.
     
    Maeslezo likes this.
  12. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    308
    Ok. That is the way I'm doing it right now and It is working, but I saw in the documentation that is a bad practice to inject the container.

    Anyway, I will keep it like that because it is working.

    Thank you!
     
  13. JaviTheGreat

    JaviTheGreat

    Joined:
    Sep 28, 2015
    Posts:
    6
    Hello Zenject team.

    Thank you for creating this awesome tool. I've been using it for a while now, and I think is very useful.

    I have a specific question about how to approach a particular challenge...
    I kind of need a GameObjectFactory that can use more than just one prefab.

    Let's say I want to create buttons of different types, but all inheriting from IPurchaseButton.
    Then I'll have several prefabs. And the Factory will create one or another depending on a parameter I'd give to it.

    Thank you,
    Javier
     
  14. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    Hey - glad you're enjoying using it.
    So the parameter would be an enum or something? Or would it be the prefab itself?

    If it's an enum or something, then you might want to use a custom factory as outlined in the docs here:
    https://github.com/modesttree/Zenject#custom-factories

    Then you can directly call "_container.InstantiatePrefabForComponent" with whatever prefab you want based on the given parameter
     
  15. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    862
    Hi! What's the proper way of using poolmanager with zenject?
     
  16. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    As stated in the FAQ, there isn't any built-in support for memory pooling. So if you need to use a memory pool, then you have to handle this yourself in some custom way. I do hope to add support for this though in the next version, since I think memory pools could fit quite nicely into it.
     
  17. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    862
    but there must be easy way of integrating 3rd party assets like poolmanager?
    Also are you planning to make better documentation?
     
  18. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    I can't comment specifically on that one (never used it) but I'm sure there is a way to integrate them.

    What's wrong with the documentation?
     
  19. halzate93

    halzate93

    Joined:
    Apr 24, 2013
    Posts:
    6
    Hi!

    I've been using Zenject for a while, works like a charm.

    However, I've found myself in situations where I need to Initialize non-active Monobehaviours. I thought about using IInitializable but then I would need to create an installer to bind each one of them as IInitializable.

    Here's an example:

    This component should be enabled whenever the DefaulDelegate event triggers. I can't subscribe on Awake because
    the dependencies have not been injected yet. Start isn't an option either, since this Monobehaviour should be enabled only when the event triggers.

    I could enable it on edit time and disable it on Start once I have subscribed to the event, but I dont really want a bunch of popups hindering my scene on Editor.

    Code (CSharp):
    1. public class QuitGamePopup : MonoBehaviour, IInitializable
    2.     {
    3.         [Inject]
    4.         private IBackNavigation backNavigation;
    5.  
    6.         [Inject]
    7.         private IPopupsDisplayer popups;
    8.  
    9.         private SimplePopupData popupData;
    10.  
    11.         public void Initialize ()
    12.         {
    13.             backNavigation.DefaultDelegate += Show;
    14.         }
    15.  
    16.         private void OnDestroy ()
    17.         {
    18.             if (backNavigation != null)
    19.                 backNavigation.DefaultDelegate -= Show;
    20.         }
    21.  
    22.         private void Show ()
    23.         {
    24.             if (popupData == null)
    25.                 popupData = CreatePopupData ();
    26.             popups.OpenOrEnqueue (popupData);
    27.         }
    28.  
    29.         private SimplePopupData CreatePopupData ()
    30.         {
    31.             SimplePopupData popupData = new SimplePopupData ();
    32.             popupData.CanGoBack = true;
    33.             popupData.TitleLabel.Text.SetLocalizationKey (StaticLocalizationKey.PopupQuitGameTitle);
    34.             popupData.DescriptionLabel.Text.SetLocalizationKey (StaticLocalizationKey.PopupQuitGameDescription);
    35.             popupData.AcceptButton.Label.Text.SetLocalizationKey (StaticLocalizationKey.GenericOkText);
    36.             popupData.AcceptButton.ClosePopupOnPress = false;
    37.             popupData.AcceptButton.PressCallback = Quit;
    38.             popupData.DeclineButton.Label.Text.SetLocalizationKey (StaticLocalizationKey.GenericCancelText);
    39.             popupData.CloseButton.Label.IsEnabled = false;
    40.             popupData.Priority.Set (PopupPriorityType.QuitGame);
    41.             return popupData;
    42.         }
    43.  
    44.         private void Quit ()
    45.         {
    46. #if UNITY_EDITOR
    47.             UnityEditor.EditorApplication.isPlaying = false;
    48. #else
    49.             Application.Quit ();
    50. #endif
    51.         }
    52.     }
    Anyone knows a better way to do this?

    Thanks!
     
  20. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    I just wanted to say thanks for the addition of pooling. It wasn't all that tough to tack on pooling before, but it makes a ton of sense for it to be included in Zenject. Unless something changes to make instantiating/destroying less costly in terms of memory/performance, pooling is going to be essential in Unity for the foreseeable future, so it's nice for it to be as convenient as possible.
     
  21. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    No problem - glad to hear that you are benefiting from it. Built-in support for pools definitely fit naturally into zenject. We had been meaning to add it for a long time - just didn't have the time until recent versions.
     
  22. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    Say I want to instantiate a prefab dynamically and have its dependencies injected. Can you provide a small example of how this might be achieved? I'm assuming use a GameObjectContext on the prefab?

    Follow-up question - for dependencies specific to this object that aren't monobehaviours, what is the proper process for destruction? Would I destroy the instances of the non-monobehaviours alongside the monobehaviour?
     
  23. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    There are several ways you can accomplish that, but you most likely want to use either a factory or pool to handle this if you're dynamically creating an unknown number of instances. A GameObjectContext is not required on the prefab unless you want/need to treat it as its own context.

    See the documentation for more info:


    Code (CSharp):
    1.  
    2. // MonoBehaviour on your prefab.
    3. public class MyPrefab : MonoBehaviour
    4. {
    5.     // Option 1. Factory
    6.     public class Factory : Zenject.PrefabFactory<MyPrefab>
    7.     {
    8.     }
    9.  
    10.     // Option 2. Pool
    11.     public class Pool : Zenject.MonoMemoryPool<MyPrefab>
    12.     {
    13.         protected override void OnCreated(MyPrefab item)
    14.         {
    15.             base.OnCreated(item);
    16.         }
    17.  
    18.         protected override void Reinitialize(MyPrefab item)
    19.         {
    20.         }
    21.  
    22.         protected override void OnSpawned(MyPrefab item)
    23.         {
    24.             base.OnSpawned(item);
    25.         }
    26.  
    27.         protected override void OnDespawned(MyPrefab item)
    28.         {
    29.             base.OnDespawned(item);
    30.         }
    31.     }
    32. }
    33.  
    34.  
    35. // Installer in scenecontext where you want to use the prefab.
    36. public class MySceneInstaller : MonoInstaller<MySceneInstaller>
    37. {
    38.     // A reference to the prefab. Only necessary here if using the pool option.
    39.     public GameObject myPrefab;
    40.  
    41.     public override void InstallBindings()
    42.     {
    43.         // Factory
    44.         Container.Bind<MyPrefab.Factory>().AsTransient();
    45.  
    46.         // Pool
    47.         Container.BindMemoryPool<MyPrefab, MyPrefab.Pool>()
    48.             .WithInitialSize(32).ExpandByOneAtATime()
    49.             .FromComponentInNewPrefab(myPrefab)
    50.             .UnderTransformGroup("MyPrefabs").NonLazy();
    51.  
    52.         // If you're going to have a fixed number of instances needed, something like this may be sufficient.
    53.         Container.Bind<MyPrefab>().FromComponentInNewPrefab(myPrefab).AsSingle();
    54.     }
    55. }
    56.  
    57. // A behvior in the scene where the factory/pool is injected.
    58. public class AnotherBehaviour : MonoBehaviour
    59. {
    60.     // A reference to the prefab. Only necessary here if using the factory option.
    61.     public GameObject myPrefab;
    62.  
    63.     [Inject]
    64.     MyPrefab.Factory prefabFactory;
    65.  
    66.     [Inject]
    67.     MyPrefab.Pool prefabPool;
    68.  
    69.     public void Start()
    70.     {
    71.         MyPrefab a = prefabFactory.Create(myPrefab);
    72.         MyPrefab b = prefabPool.Spawn();
    73.     }
    74. }
     
    Last edited: Dec 8, 2017
    Exeneva likes this.
  24. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    @chasepettit , thanks for the prompt reply. The reason I mentioned the GameObjectContext is because the prefab has its own dependencies that will need to be injected. If I instantiate with a factory or pool, how would I ensure these dependencies are wired up correctly after instantiation?
     
  25. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    @Exeneva I'm not totally sure what you're asking or what you're trying to do. Anything that has been bound in the scene/project context would be injected into the prefab instance when the pool/factory creates it. The factory and pool also let you pass in additional parameters that will be bound to the specific instance when you call "Create" or "Spawn" - this is the typical way to customize individual instances to have different behavior.
     
    Exeneva likes this.
  26. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    @chasepettit , what I mean is, the monobehaviour has a View class attached, but has dependencies to non-monobehaviour Model and Controller classes. I don't want the Model and Controller to be singletons (can't mark them AsSingle() ) so I am curious how to make individual bindings for each instance of the View that will be spawned. This is originally why I was thinking I needed to use GameObjectContext.
     
  27. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    Ah. I think understand now. So, each View will receive its own instance of the Model and Controller class, but everything in the context of that given View should use the same instance - is this what you mean?

    In that case, you're correct that you will probably want to use a GameObjectContext. Basically, what you can do is have an installer on the GameObjectContext that receives an injected Model/Controller from its parent context and then binds it so that everything else in that GameObjectContext will refer to that single instance - see the FromInstance()/BindInstance() construction options in the documentation. Also check out the documentation and examples on SubContainers if you haven't already (the last section in particular): https://github.com/modesttree/Zenject/blob/master/Documentation/SubContainers.md
     
    Last edited: Dec 10, 2017
    Exeneva likes this.
  28. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    Would the parent context inject the model / controller AsSingle() ?
    I'm unsure on the scope of it.

    The last example demonstrates a Factory creating a gameobject dynamically and injecting into its GameObjectContext - how would it look for a Pool?
     
  29. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    Anything you bind in the GameObjectContext installer is just going to be bound within that context, they don't necessarily need to be bound at all in the SceneContext if they're not being used there.

    Some of this stuff is confusing to learn initially, but once you use it for a while, it should start to become a bit more intuitive. You may still need to look up API specifics, but you'll at least be able to see how the pieces should fit together.

    Here's a quick example. We'll use a Pool to create our View objects and provide each one with its own Model and Controller generated from a Factory.

    Code (CSharp):
    1.  
    2.  
    3. public class SceneInstaller : MonoInstaller<SceneInstaller>
    4. {
    5.     public GameObject viewPrefab;
    6.  
    7.     public override void InstallBindings()
    8.     {
    9.         // We'll use a factory to create our Model/Controller instances.
    10.         // Alternatively, we could just have Model/Controller bound AsTransient and
    11.         // then each View GameObjectContext would get its own instance just like everything
    12.         // else that uses Model/Controller in this context.
    13.         Container.BindFactory<Model, Model.Factory>();
    14.         Container.BindFactory<Controller, Controller.Factory>();
    15.  
    16.         Container.BindMemoryPool<View, View.Pool>()
    17.             .WithInitialSize(32).ExpandByOneAtATime()
    18.             .FromComponentInNewPrefab(viewPrefab).NonLazy();
    19.     }
    20. }
    21.  
    22. // Some MonoBehaviour where you're spawning View objects.
    23. public class ViewCreator : MonoBehaviour
    24. {
    25.     [Inject] View.Pool viewPool;
    26.     [Inject] Model.Factory modelFactory;
    27.     [Inject] Controller.Factory controllerFactory;
    28.  
    29.     public void DoSomething()
    30.     {
    31.         Model modelForView = modelFactory.Create();
    32.         Controller controllerForView = controllerFactory.Create();
    33.  
    34.         View view = viewPool.Spawn(modelForView, controllerForView);
    35.     }
    36. }
    37.  
    38. // This would be one of the installers on your View prefab's GameObjectContext.
    39. public class ViewInstaller : MonoInstaller<ViewInstaller>
    40. {
    41.     // Model/Controller instances that are injected by parent context.
    42.     [Inject] private Model model;
    43.     [Inject] private Controller controller;
    44.  
    45.     public override void InstallBindings()
    46.     {
    47.         // We'll bind these specific instances of Model/Controller.
    48.         // Everything in this GameObjectContext will be injected with this specific instace of these classes.
    49.         Container.BindInstance(model); // or alternatively: Container.Bind<Model>().FromInstance(model);
    50.         Container.BindInstance(controller);
    51.     }
    52. }
    53.  
    54. // MonoBehaviour on your View GameObject.
    55. public class View : MonoBehaviour
    56. {
    57.     // These will be the specific instances that we bound in ViewInstaller.
    58.     [Inject] private Model model;
    59.     [Inject] private Controller controller;
    60.  
    61.     public class Pool : MonoMemoryPool<Model, Controller, View>
    62.     {
    63.         protected override void OnCreated(View item)
    64.         {
    65.             base.OnCreated(item);
    66.         }
    67.         protected override void Reinitialize(Model model, Controller controller, View item)
    68.         {
    69.         }
    70.         protected override void OnSpawned(View item)
    71.         {
    72.             base.OnSpawned(item);
    73.         }
    74.         protected override void OnDespawned(View item)
    75.         {
    76.             base.OnDespawned(item);
    77.         }
    78.     }
    79. }
     
    Last edited: Dec 10, 2017
    Exeneva likes this.
  30. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    I deleted my prior post as it was lengthy. This is basically the issue I'm having trouble with:

    - Controller has a dependency on View, so it can't be instantiated with the View pool, it has to be created (using Factory) after a View has been created, and then the View must be bound to that instance of the Controller.

    How would you approach a situation like this? Do you typically design the architecture of player gameobjects differently?
     
  31. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    @Exeneva You've created a pretty classic case of a circular dependency.

    There are a lot of possible solutions, but it's kinda going to be up to you to decide the best approach based on your current architecture.

    Is it possible that View and Controller are so co-dependent that they should just be a single class or both live behind a single Facade class? Is there some specific aspect of View or Controller that can be broken out into a separate class, such that View and Controller can each share an instance of this third class but won't have to depend on each other? Rather than injecting an instance of View/Controller, could you possibly just inject the factory itself - for instance, inject Controller.Factory into View, View passes itself into the call to Controller.Factory.Create.
     
  32. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    I decided to combine my Controller into my View. Now I only have a View and a Model. The View has a dependency on Model, but the Model does not depend on View.

    I tried the above configuration you suggested (removing the Controller code), but I'm still getting a scene graph validation error:

    ZenjectException: Unable to resolve type 'Model' while building object with type 'ViewInstaller'.
    Object graph:
    ViewInstaller

    I think it's because when you spawn the memory pool of View objects, each View requires an instance of a Model. We bind the Factory for the Model but we didn't bind an instance of a Model for each View object that's nonlazily instantiated in the pool. Or maybe I'm missing something else here?

    EDIT: I reached out to the Zenject author and he said this:

    Factories always instantiate their instances within the container that the factory is defined in. So in this case, it would create EnemyShipModel in the higher level container and not in your game object context. Can you use Container.Bind<EnemyShipModel>().AsSingle() instead?

    I tried this and it worked :)
     
    Last edited: Dec 14, 2017
  33. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    @chasepettit , is there a way to inject into a ScriptableObject?

    Right now, I'm trying to inject a Signal into one, but I'm getting a nullreference exception. I'm very confident my signal binding isn't wrong since my other signals are also working. I'm actually wondering if this is a limitation of Zenject.
     
  34. chasepettit

    chasepettit

    Joined:
    Oct 23, 2012
    Posts:
    42
    I mostly just use ScriptableObjects as inert data containers, so I've never attempted to do that.

    It does seem like this is something that Zenject would need to have some code written specifically to accommodate since ScriptableObjects aren't instantiated or loaded in quite the same way as GameObjects/Prefabs/MonoBehaviours.
     
  35. Exeneva

    Exeneva

    Joined:
    Dec 7, 2013
    Posts:
    432
    Alright, so here's what I'm actually trying to do.
    I have a state machine where each state is a scriptableobject.
    In one of those states, I am trying to inject a signal to handle the player death and transition to the GAME_OVER state.

    Unfortunately, Zenject doesn't play nice with scriptableobjects. If I want to keep my states as SOs, what would be my options?
     
  36. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    According to the code it should be injecting scriptable objects, when you bind them using FromScriptableObjectResource or FromNewScriptableObjectResource. Are you using FromInstance? If so, you can follow that up with Container.QueueForInject(instance) to have them injected after the install phase completes.
     
    Exeneva likes this.
  37. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    249
    Anyone interested in further updates to Zenject should be aware that the primary author (me) is continuing it under the name Extenject instead, which you can find at https://github.com/svermeulen/Extenject
     
    nikolay_i and Mr-Knieves like this.
  38. free4allgames

    free4allgames

    Joined:
    Dec 5, 2018
    Posts:
    42
    github page says it's removed from the Asset Store because of a lawsuit, but it's on the Asset Store now, is the lawsuit over?
     
  39. a-t-hellboy

    a-t-hellboy

    Joined:
    Dec 6, 2013
    Posts:
    180
    Hey guys, I'm stuck on something about Zenject/Extenject. Any one has any idea how I can fix that ?

    I have Player gameObject with Game Object Context which instantiate Character prefab by factory and Charcater has Game Object Context. In CharacterController which is a facade class on Character I instantiate a few Scriptable Objects in this way:

    Code (CSharp):
    1. private readonly DiContainer _container;
    2.  
    3. public ZenjectResourceFactory(DiContainer container)
    4. {
    5.     _container = container;
    6. }
    7. public Object Instantiate(Object @object)
    8. {
    9.     Object instance = Object.Instantiate(@object);
    10.     _container.QueueForInject(instance);
    11.     return instance;
    12. }
    In the Character Installer CharacterBehavior and CharacterPowerup are bound by Container.Bind<CharacterBehaviorContext>().AsSingle().NonLazy(); and Container.Bind<CharacterPowerupContext>().AsSingle().NonLazy();

    But the issue is CharacterBehavior and CharacterPowerup are not injected into those Scriptable Objects [Inject] methods.