diff --git a/Build/CreateHtmlDocs.bat b/Build/CreateHtmlDocs.bat index a878b801e..ee57b09a6 100644 --- a/Build/CreateHtmlDocs.bat +++ b/Build/CreateHtmlDocs.bat @@ -1,11 +1,11 @@ @echo off -grip %~dp0\..\README.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\README.html -grip %~dp0\..\Documentation\AutoMocking.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\AutoMocking.html -grip %~dp0\..\Documentation\CheatSheet.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\CheatSheet.html -grip %~dp0\..\Documentation\Signals.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\Signals.html -grip %~dp0\..\Documentation\Factories.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\Factories.html -grip %~dp0\..\Documentation\MemoryPools.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\MemoryPools.html -grip %~dp0\..\Documentation\ReleaseNotes.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\ReleaseNotes.html -grip %~dp0\..\Documentation\SubContainers.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\SubContainers.html -grip %~dp0\..\Documentation\WritingAutomatedTests.md --export %~dp0\..\UnityProject\Assets\Zenject\Documentation\WritingAutomatedTests.html +grip %~dp0\..\README.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\README.html +grip %~dp0\..\Documentation\AutoMocking.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\AutoMocking.html +grip %~dp0\..\Documentation\CheatSheet.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\CheatSheet.html +grip %~dp0\..\Documentation\Signals.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\Signals.html +grip %~dp0\..\Documentation\Factories.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\Factories.html +grip %~dp0\..\Documentation\MemoryPools.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\MemoryPools.html +grip %~dp0\..\Documentation\ReleaseNotes.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\ReleaseNotes.html +grip %~dp0\..\Documentation\SubContainers.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\SubContainers.html +grip %~dp0\..\Documentation\WritingAutomatedTests.md --export %~dp0\..\UnityProject\Assets\Plugins\Zenject\Documentation\WritingAutomatedTests.html diff --git a/UnityProject/Assets/Plugins/Zenject/Documentation/Factories.html b/UnityProject/Assets/Plugins/Zenject/Documentation/Factories.html index ad5f192df..4cf3541d6 100644 --- a/UnityProject/Assets/Plugins/Zenject/Documentation/Factories.html +++ b/UnityProject/Assets/Plugins/Zenject/Documentation/Factories.html @@ -215,6 +215,10 @@

The dynamic parameters that are provided to the Enemy constructor are declared by using generic arguments to the Factory<> base class of Enemy.Factory. This will add a method to Enemy.Factory that takes the parameters with the given types, which is called by EnemySpawner.

+

Note: You can have multiple parameters declared with the same type. In this case, the order that the values are given to the factory will match the parameter order - assuming that you are using constructor or method injection. However, if you are using field or property injection, then the order that values are injected is not guaranteed to follow the declaration order, since these fields are retrieved using Type.GetFields which does not guarantee order as described here

+ +

In this case, they will be injected in the same order that they are declared in your class. In the case of constructor/inject-method parameters, this will be the order the parameters are given in, or in the case of fields the order will be from top to bottom that they are declared in. Constructor parameters are processed first, then fields, then properties, then inject methods.

+

There is no requirement that the Enemy.Factory class be a nested class within Enemy, however we have found this to be a very useful convention. Enemy.Factory is always intentionally left empty and simply derives from the built-in Zenject Factory<> class, which handles the work of using the DiContainer to construct a new instance of Enemy.

The reason that we don't use the Factory<Enemy> class directly is because this can become error prone when adding/removing parameters and also can get verbose since the parameter types must be declared whenever you refer to this class. This is error prone because if for example you add a parameter to enemy and change the factory from Factory<Enemy> to Factory<float, Enemy>, any references to Factory<Enemy> will not be resolved. And this will not be caught at compile time and instead will only be seen during validation or runtime. So we recommend always using an empty class that derives from Factory<> instead.

@@ -258,6 +262,8 @@

Using FromSubContainerResolve can be particularly useful if your dynamically created object has a lot of its own dependencies. You can have it behave like a Facade. See the Subcontainers section for details on nested containers / facades.

+

Also note that you for dynamically instantiated MonoBehaviours (for example when using FromComponentInNewPrefab with BindFactory) injection should always occur before Awake and Start, so you can use Awake and Start for initialization logic and use the inject method strictly for saving dependencies (ie. similar to constructors for non-monobehaviours)

+

Abstract Factories

diff --git a/UnityProject/Assets/Plugins/Zenject/Documentation/MemoryPools.html b/UnityProject/Assets/Plugins/Zenject/Documentation/MemoryPools.html index 1c3efce5b..5e20c8e0e 100644 --- a/UnityProject/Assets/Plugins/Zenject/Documentation/MemoryPools.html +++ b/UnityProject/Assets/Plugins/Zenject/Documentation/MemoryPools.html @@ -182,7 +182,7 @@

The full format of the binding is the following:

-Container.BindMemoryPool<Param1Type, Param2Type, etc..., ObjectType, MemoryPoolType>()
+Container.BindMemoryPool<ObjectType, MemoryPoolType>()
     .With(InitialSize|FixedSize)()
     .ExpandBy(OneAtATime|Doubling)()
     .To<ResultType>()
@@ -448,7 +448,7 @@ 

The main difference here is that Foo.Pool now derives from MonoMemoryPool instead of MemoryPool. MonoMemoryPool is a helper class that will automatically enable and disable the game object for us when it is added/removed from the pool. The implementation for MonoMemoryPool is simply this:

-
public abstract class MonoMemoryPool<TParam1, TValue> : MemoryPool<TParam1, TValue>
+
public abstract class MonoMemoryPool<TParam1, TValue> : MemoryPool<TParam1, TValue>
     where TValue : Component
 {
     protected override void OnCreated(TValue item)
@@ -536,6 +536,30 @@ 

We might also want to add a Reset() method to the IFoo interface as well here, and call that on Reinitialize()

+

+Instantiating Memory Pools Directly

+ +

For complex scenarios involing custom factories, it might be desirable to directly instantiate memory pools. In this case, you just have to make sure to provide an IFactory<> derived class to be used for creating new instances and all the settings information that would normally be provided via the bind statements. For example:

+ +
public class BarFactory : IFactory<Bar>
+{
+    public Bar Create()
+    {
+        ...
+        [Custom creation logic]
+        ...
+    }
+}
+
+var settings = new MemoryPoolSettings()
+{
+    InitialSize = 1,
+    ExpandMethod = PoolExpandMethods.Double,
+};
+
+var pool = _container.Instantiate<MemoryPool<Bar>>(
+    new object[] { settings, new MyBarFactory<Bar>() });
+
diff --git a/UnityProject/Assets/Plugins/Zenject/Documentation/ReadMe.html b/UnityProject/Assets/Plugins/Zenject/Documentation/ReadMe.html index 997247a96..8f7a084c2 100644 --- a/UnityProject/Assets/Plugins/Zenject/Documentation/ReadMe.html +++ b/UnityProject/Assets/Plugins/Zenject/Documentation/ReadMe.html @@ -56,7 +56,7 @@

Join the chat at https://gitter.im/Zenject/Lobby

-

If you are looking for the older documentation for Zenject 3.X click here.

+

If you are looking for the older documentation for Zenject 3.X click here and for 4.x click here.

Many hours have gone into the creation of this framework and many more will go to continue maintaining it. If you or your team have found it useful, consider buying me a coffee! Every donation makes me significantly more likely to find time for it.

@@ -77,6 +77,7 @@

  • Android
  • Webplayer
  • WebGL
  • +
  • PS4 (with IL2CPP backend)
  • Windows Store (including 8.1, Phone 8.1, Universal 8.1 and Universal 10 - both .NET and IL2CPP backend)
  • @@ -144,7 +145,7 @@

    From Source

      -
    • You can also just clone this repo and copy the UnityProject/Assets/Zenject directory to your own Unity3D project. In this case, make note of the folders underneath "OptionalExtras" and choose only the ones you want.
    • +
    • You can also just clone this repo and copy the UnityProject/Assets/Plugins/Zenject directory to your own Unity3D project. In this case, make note of the folders underneath "OptionalExtras" and choose only the ones you want.
    @@ -399,7 +400,7 @@

    public override void InstallBindings() { Container.Bind<string>().FromInstance("Hello World!"); - Container.Bind<Greeter>().NonLazy(); + Container.Bind<Greeter>().AsSingle().NonLazy(); } } @@ -495,6 +496,10 @@

    Using [Inject] methods to inject dependencies is the recommended approach for MonoBehaviours, since MonoBehaviours cannot have constructors.

    +

    Also note that you can define your inject methods to have return type IEnumerator. In this case, they will be started as a coroutine. In the case where the object is a MonoBehaviour, it will be started as a coroutine on itself, and otherwise it will use the "Context" MonoBehaviour that the object is in (that is, either ProjectContext, SceneContext or GameObjectContext)

    + +

    Note however that we would recommend minimizing the initialization logic in [Inject] methods however. You can use Start() or Awake() to have initialization logic instead (this should work for both dynamically instantiated prefabs and objects added to the scene during edit time).

    +

    Recommendations

    Best practice is to prefer constructor injection or method injection to field or property injection.

    @@ -747,6 +752,8 @@

    Container.Bind<Foo>().FromNewComponentSibling();
    +

    Note that if the given component type is already attached to the current transform that this will just return that instead of creating a new component. As a result, this bind statement functions similar to Unity's [RequireComponent] attribute.

    +

    ResultType must derive from UnityEngine.MonoBehaviour / UnityEngine.Component in this case

    Also note that if a non-MonoBehaviour requests the given type, an exception will be thrown, since there is no current transform in that case.

    @@ -911,7 +918,7 @@

    You add bindings by overriding the InstallBindings method, which is called by whatever Context the installer has been added to (usually this is SceneContext). MonoInstaller is a MonoBehaviour so you can add FooInstaller by attaching it to a GameObject. Since it is a GameObject you can also add public members to it to configure your installer from the Unity inspector. This allows you to add references within the scene, references to assets, or simply tuning data (see here for more information on tuning data).

    -

    Note that in order for your installer to be triggered it must be attached to the Installers property of the SceneContext object. The installers are executed in the order given to SceneContext however this order should not usually matter (since nothing should be instantiated during the install process)

    +

    Note that in order for your installer to be triggered it must be attached to the Installers property of the SceneContext object. Installers in the order given to SceneContext (with scriptable object installers first, then mono installers, then prefab installers) however this order should not usually matter (since nothing should be instantiated during the install process).

    In many cases you want to have your installer derive from MonoInstaller, so that you can have inspector settings. There is also another base class called simply Installer which you can use in cases where you do not need it to be a MonoBehaviour.

    @@ -1356,7 +1363,7 @@

    ## <a id="game-object-bind-methods"></a>Game Object Bind Methods -For bindings that create new game objects (eg. FromComponentInNewPrefab or FromGameObject) there are also two extra bind methods. +For bindings that create new game objects (eg. FromComponentInNewPrefab or FromNewComponentOnNewGameObject) there are also two extra bind methods. * **WithGameObjectName** = The name to give the new Game Object associated with this binding. @@ -2703,7 +2710,43 @@

  • Does this work on AOT platforms such as iOS and WebGL?

    -

    Yes. However, there are a few things that you should be aware. One of the things that Unity's IL2CPP compiler does is strip out any code that is not used. It calculates what code is used by statically analyzing the code to find usage. This is great, except that this will miss any methods/types that are not used explicitly. In particular, any classes that are created solely through Zenject will have their constructors ignored by the IL2CPP compiler. In order to address this, the [Inject] attribute that is sometimes applied to constructors also serves to automatically mark the constructor to IL2CPP to not strip out. In other words, to fix this issue all you have to do is mark every constructor that you create through Zenject with an [Inject] attribute when compiling for WebGL / iOS.

    +

    Yes. However, there are a few things that you should be aware of. One of the things that Unity's IL2CPP compiler does is strip out any code that is not used. It calculates what code is used by statically analyzing the code to find usage. This is great, except that this will miss any methods/types that are not used explicitly. In particular, any classes that are created solely through Zenject will have their constructors ignored by the IL2CPP compiler. In order to address this, the [Inject] attribute that is sometimes applied to constructors also serves to automatically mark the constructor to IL2CPP to not strip out. In other words, to fix this issue all you have to do is mark every constructor that you create through Zenject with an [Inject] attribute when compiling for WebGL / iOS.

    + +

    Sometimes, an exception to this rule is classes that have generic arguments and which are instantiated with a "value type" generic argument (eg. int, float, enums, anything deriving from struct, etc.). In this case, compiling with AOT will sometimes strip out the constructor, so Zenject will not be able to create the class and you will get a runtime error. For example:

    + +
        public class Foo<T1>
    +    {
    +        public Foo()
    +        {
    +            Debug.Log("Successfully created Foo!");
    +        }
    +    }
    +
    +    public class Runner2 : MonoBehaviour
    +    {
    +        public void OnGUI()
    +        {
    +            if (GUI.Button(new Rect(100, 100, 500, 100), "Attempt to Create Foo"))
    +            {
    +                var container = new DiContainer();
    +
    +                // This will throw exceptions on AOT platforms because the constructor for Foo<int> is stripped out of the build
    +                container.Instantiate<Foo<int>>();
    +
    +                // This will run fine however, because string is not value type
    +                //container.Instantiate<Foo<string>>();
    +            }
    +        }
    +
    +        static void _AotWorkaround()
    +        {
    +            // As a workaround, we can explicitly reference the constructor here to force the AOT
    +            // compiler to leave it in the build
    +            // new Foo<int>();
    +        }
    +    }
    + +

    Normally, in a case like above where a constructor is being stripped out, we can force-include it by adding the [Inject] attribute on the Foo constructor, however this does not work for classes with generic types that include a value type. Therefore, the recommended workarounds here are to either explicitly reference the constructor similar to what you see in the _AotWorkaround, or avoid using value type generic arguments. One easy way to avoid using value types is to wrap it in a reference type (for example, by using something like this)

  • How is performance?

    @@ -2762,7 +2805,7 @@

    public override void InstallBindings() { Container.Bind<IInitializable>().To<Foo>().AsSingle(); - Container.Bind<AsyncProcessor>().FromGameObject().AsSingle(); + Container.Bind<AsyncProcessor>().FromNewComponentOnNewGameObject().AsSingle(); } }

  • @@ -2797,6 +2840,8 @@

    Untethered (Google VR)
  • Toy Clash - (GearVR)
  • +
  • +Bedtime Math App - (iOS and Android)
  • Libraries

    diff --git a/UnityProject/Assets/Plugins/Zenject/Documentation/ReleaseNotes.html b/UnityProject/Assets/Plugins/Zenject/Documentation/ReleaseNotes.html index b7e3acce9..b12e8a9f7 100644 --- a/UnityProject/Assets/Plugins/Zenject/Documentation/ReleaseNotes.html +++ b/UnityProject/Assets/Plugins/Zenject/Documentation/ReleaseNotes.html @@ -53,11 +53,72 @@

    Release Notes

    -5.0 (February 11, 2017)

    +5.1.0 (April 3, 2017) + +

    Notable

    + + + +

    Minor

    + + + +

    +5.0.2 (March 5, 2017)

    + + + +

    +5.0.1 (February 15, 2017)

    + + + +

    +5.0 (February 13, 2017)

    + +

    Summary

    + +

    Notable parts of this release includes the long awaited support for Memory Pools, a re-design of Commands/Signals, and support for late resolve via Lazy<> construct. It also includes some API breaking changes to make it easier for new users. Some of the bind methods were renamed to better represent what they mean, and in some cases the scope is now required to be made explicit, to avoid accidentally using transient scope. Finally, there was also some significant performance improvements for when using Zenject in scenes with many transforms.

    New Features

    - -

    Optimizations

    - - - -

    Breaking changes

    - -