Update and Initialization Order - mariaheine/Zenject-But-Wiki GitHub Wiki
In many cases, especially for small projects, the order that classes update or initialize in does not matter. However, in larger projects update or initialization order can become an issue. This can especially be an issue in Unity, since it is often difficult to predict in what order the Start()
, Awake()
, or Update()
methods will be called in. Unfortunately, Unity does not have an easy way to control this (besides in Edit -> Project Settings -> Script Execution Order
, though that can be awkward to use)
In Zenject, by default, ITickables and IInitializables are called in the order that they are added, however for cases where the update or initialization order does matter, there is another way that is sometimes better: By specifying their priorities explicitly in the installer. For example, in the sample project you can find this code in the scene installer:
public class AsteroidsInstaller : MonoInstaller
{
...
void InitExecutionOrder()
{
// In many cases you don't need to worry about execution order,
// however sometimes it can be important
// If for example we wanted to ensure that AsteroidManager.Initialize
// always gets called before GameController.Initialize (and similarly for Tick)
// Then we could do the following:
Container.BindExecutionOrder<AsteroidManager>(-10);
Container.BindExecutionOrder<GameController>(-20);
// Note that they will be disposed of in the reverse order given here
}
...
public override void InstallBindings()
{
...
InitExecutionOrder();
...
}
}
This way, you won't hit a wall at the end of the project due to some unforeseen order-dependency.
Note here that the value given to BindExecutionOrder
will apply to ITickable
/ IInitializable
and IDisposable
(with the order reversed for IDisposable
's).
You can also assign priorities for each specific interface separately like this:
Container.BindInitializableExecutionOrder<Foo>(-10);
Container.BindInitializableExecutionOrder<Bar>(-20);
Container.BindTickableExecutionOrder<Foo>(10);
Container.BindTickableExecutionOrder<Bar>(-80);
Any ITickables, IInitializables, or IDisposables that are not assigned a priority are automatically given the priority of zero. This allows you to have classes with explicit priorities executed either before or after the unspecified classes. For example, the above code would result in Foo.Initialize
being called before Bar.Initialize
.