Giter Club home page Giter Club logo

Comments (16)

svermeulen avatar svermeulen commented on July 28, 2024

I think this should do what you want:

    public static void ToPrefab<T>(this BinderGeneric<T> binder, String prefabLocation)
        where T : UnityEngine.Object
    {
        binder.ToMethod((ctx) =>
            {
                return ctx.Container.InstantiatePrefabForComponent<T>((GameObject)Resources.Load(prefabLocation));
            });
    }

Untested though, so let me know.

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

Thanks for the response! I am getting an exception

ZenjectException: Assert Hit! Found null pointer when value was expected
ModestTree.Assert.Throw (System.String message) (at Assets/Lib/Zenject/Internal/Assert.cs:195)
ModestTree.Assert.IsNotNull (System.Object val) (at Assets/Lib/Zenject/Internal/Assert.cs:128)
Zenject.DiContainer.InstantiatePrefabForComponentExplicit (System.Type componentType, UnityEngine.GameObject prefab, System.Collections.Generic.List`1 extraArgs, Zenject.InjectContext currentContext) (at Assets/Lib/Zenject/Main/Scripts/Main/DiContainer.cs:856)
Zenject.DiContainer.InstantiatePrefabForComponentExplicit (System.Type concreteType, UnityEngine.GameObject prefab, System.Collections.Generic.List`1 extraArgMap) (at Assets/Lib/Zenject/Main/Scripts/Main/DiContainer.cs:983)
Zenject.DiContainer.InstantiatePrefabForComponent (System.Type concreteType, UnityEngine.GameObject prefab, System.Object[] extraArgs) (at Assets/Lib/Zenject/Main/Scripts/Main/DiContainer.cs:969)
Zenject.DiContainer.InstantiatePrefabForComponent[ElementoInteractivoPresenter] (UnityEngine.GameObject prefab, System.Object[] extraArgs) (at Assets/Lib/Zenject/Main/Scripts/Main/DiContainer.cs:960)
uMVC.Extensions+<ToPrefab>c__AnonStorey76`1[Arista.Presenters.ElementoInteractivoPresenter].<>m__B4 (Zenject.Injec

I split the extension method into multiple lines

            binder.ToMethod((ctx) => {
                var obj = Resources.Load(prefabLocation) as GameObject;
                Debug.Log(obj);
                var component = ctx.Container.InstantiatePrefabForComponent<T>(obj);
                Debug.Log(component);
                return component;
            });

and found that its on ctx.Container.InstantiatePrefabForComponent but var obj is not null.

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

Can you try changing any method that starts with InstantiatePrefab in DiContainer.cs and IInstantiator.cs to take a UnityEngine.Object instead of a GameObject?

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

Oh, wait, from your debug outputs that actually suggests that cast worked fine.

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

So, assuming the prefab you're giving to it is fine then I think I need more context about how you're initializing your container. Can you upload a minimal example showing the issue?

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

Small example.

Project structure

  • Resources
    • Tests
      • FooMono.cs
      • TestPrefabInjection.cs
      • FooMonoPrefab.prefab

where FooMonoPrefab contains a FooMono component.

Scene

  • App

where App gameobject contains a TestPrefabInjection component. As noted, this is the initial configuration and is expected to spawn a FooMonoPrefab.

FooMono.cs

using UnityEngine;
using System.Collections;
using Zenject;

public class FooMono : MonoBehaviour {

    [PostInject]
    public void Post() {
        print("Post");
    }
}

TestPrefabInjection.cs

using UnityEngine;
using System.Collections;
using Zenject;

public class TestPrefabInjection : MonoBehaviour {

    // Use this for initialization
    void Start () {
        var container = new DiContainer();
        container.Bind<FooMono>().ToPrefab("Tests/FooMonoPrefab");
        container.Resolve(typeof(FooMono));
    }
}

public static class Extensions
{

    public static void ToPrefab<T>(this BinderGeneric<T> binder, string prefabLocation) where T : UnityEngine.Object
    {

        binder.ToMethod((ctx) => {
            var obj = Resources.Load(prefabLocation) as GameObject;
            Debug.Log(obj);
            var component = ctx.Container.InstantiatePrefabForComponent<T>(obj);
            Debug.Log(component);
            return component;
        });
    }
}

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

Thanks, that's very helpful.

The issue is that the DiContainer is not initialized with a root transform, so it doesn't know where to parent new objects to. So you just need to change it so that it uses the other DiContainer constructor, which takes a transform.

I was assuming you were working in a scene with CompositionRoot and Installers, etc. which does that for you.

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

Thanks a lot @svermeulen ! I just started using Zenject yesterday, can you show me how to modify TestPrefabInjection.cs so it works? Or do I have to do something else?

PS: Once I understand Zenject better I'll send a pull request on the Getting Started section of the readme. You leave some things to the imagination ;)

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

Sure, here's how I would do it:

Create a new game object and attach a SceneCompositionRoot to it. Create another new game object and attach this script to it:

public class TestInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<FooMono>().ToPrefab("Tests/FooMonoPrefab");
    }
}

Then drag the game object into the Installers property of the CompositionRoot. Then create another game object underneath the composition root and attach this script to it:

public class BarMono : MonoBehaviour
{
    FooMono _foo;

    [PostInject]
    public void Initialize(FooMono foo)
    {
        _foo = foo;
    }
}

You shouldn't have to change your extension method.

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

@svermeulen thanks for all your time! I am just missing a little piece: how do I get the container that installed stuff onto TestPrefabInjection.cs or any other part of my code? Also, is there a way of not having to create these extra constructs? I would like users not having to setup their scene in any particular way.

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

Yep, you don't need to use these constructs like CompositionRoot / Installers / ITickable / etc. You should be able to just new up a DiContainer and use it however you like.

So, with that in mind, I just pushed a change that does allow having a null value for the root transform. So your original code should work now if you update from this git repo. In that case it will just create any new objects at the root of your scene instead of parenting it the given transform

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

Sorry, what i mean is, your original code plus the first suggestion I made for your extension method:

    public static void ToPrefab<T>(this BinderGeneric<T> binder, String prefabLocation)
        where T : UnityEngine.Object
    {
        binder.ToMethod((ctx) =>
            {
                return ctx.Container.InstantiatePrefabForComponent<T>((GameObject)Resources.Load(prefabLocation));
            });
    }

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

@svermeulen Thank you very much! I already got it working linking the a public SceneCompositionRoot root through the editor on TestPrefabInjection. I'll commit my repo and get the updates!

BTW: I'll opensource the MVC library once its stable :)

from zenject-2019.

svermeulen avatar svermeulen commented on July 28, 2024

No problem - glad you got it working :)

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

Changes worked perfectly :) ! Didn't have to change any of my project code other than the extension method.

from zenject-2019.

cgarciae avatar cgarciae commented on July 28, 2024

Ok here is the grand idea. I'd like to have a custom [Route(String location)] annotation so the user doesn't have to setup the routes itself. Look at the modified slightly modified FooMono

using UnityEngine;
using System.Collections;
using Zenject;

[Route("Tests/FooMonoPrefab")]
public class FooMono : MonoBehaviour {

    [PostInject]
    public void Post() {
        print("Post");
    }
}

Elsewhere you create a class like this

public class MyApp : MVCApp {
    public void ConfigureServices(IServiceCollection services) {
        //Configures services
    }

    public void Configure(IApplicationBuilder app, DiContainer container) {
        //Setup your dependencies using the container
    }
}

Routes can also request an IRouter and an IRequest so an example might look like this

[Route("Tests/FooMonoPrefab")]
public class FooMono : MonoBehaviour {
    IRouter router;

     [PostInject]
    public void MonoConstructor(IRequest request, IRouter router) {
        this.router = router;
        print(request.parameters["param"]);
    }

    void GoToSomeRoute() {
        router.GoTo(
            url: "some/route",
            parameters: new Dictionary<String, String> () {
                {"param", "value"}
            },
            body: someObject
        );
    }
}

from zenject-2019.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.