Lifecycle changes
Lifecycle changes in Application
Historically you had 2 methods that were mainly used for setting up your application:
ApplicationStarting
- Modules are loaded, go prep your appApplicationStarted
- Everything is loaded, go use your app
This was fine to begin with but does not scale well when you have more complex scenarios or plugins that augment the internal parts of the framework.
v2 Lifecycle changes
So as part of trying to improve this workflow the lifecycle has now been changed to have several virtual methods which you can opt in to plug in your own logic, here is a list of the methods and the order they run in.
1. LoadModules
This is where you should load your own modules, the base.LoadModules()
will load the default framework so if you do not want this and want to load your own optimized framework components just dont call the base version. An example of this is shown in the optimized performance tests where we are manually assigning the component type ids so we do not want the default loader.
2. LoadPlugins
This is where you should load any plugins you want to use, if you have no plugins to use then dont bother overriding it.
One major change in plugin loading is that it now happens before internal dependencies are resolved, as historically this was run AFTER certain dependencies were resolved such as ISystemExecutor
and IEventSystem
so if you had a plugin which removed base bindings and put its own in, you would be unable to consume them as the application had already resolved the things it was changing, so this now allows plugins to augment the framework and application dependencies before they are resolved, which makes everything more flexible.
3. ResolveApplicationDependencies
This is where the dependencies of the application are manually resolved from the DI Container, so the ISystemExecutor
and IEventSystem
etc are all resolved at this point, once all plugins and modules are run. The base.ResolveApplicationDependencies()
will setup the core EcsRxApplication dependencies so you should call this then resolve anything specific you need after this point.
4. BindSystems
This is where all systems are BOUND (which means they are in the DI container but not resolved), by default it will auto bind all systems within application scope (using BindAllSystemsWithinApplicationScope
), however you can override and remove the base call if you do not want this behaviour, or if you want to manually register other systems you can let it auto register systems within application scope and then manually bind any other systems you require.
5. StartSystems
This is where all systems that are bound should be started (they are added to the ISystemExecutor
), by default this stage will add all bound systems to the active system executor (using StartAllBoundSystems
), however you can override this behaviour to manually control what systems are to be started, but in most cases this default behaviour will satisfy what you want.
6. ApplicationStarted
Much like the old world, this is where you should start using everything, by this point:
- All the dependencies you require for everything should be bound
- All the plugins you require should be loaded and initialized
- All the systems you require should be in the systems executor
So from here you can just get on with making your entities and starting your game, but as you can see you now have far more flexibility and structure to how you compose your application and in default scenarios you will generally get everything loaded for you ready to go assuming default conventions.