Loading
One of the most important aspects of the AlchemyBow.Core is to provide an easy and organized way to handle loading processes.
ICoreLoadable
ICoreLoadable is an interface for objects that require a time-consuming loading process. It provides one method - Load(OperationHandle)
that takes the OperationHandle as a parameter.
The loading process is considered complete when you call OperationHandle.MarkDone()
.
using AlchemyBow.Core;
using System.Collections;
using UnityEngine;
public class SampleCoreLoadable : MonoBehaviour, ICoreLoadable
{
public void Load(OperationHandle handle)
{
StartCoroutine(CreateLoadCoroutine(handle));
}
private IEnumerator CreateLoadCoroutine(OperationHandle handle)
{
yield return new WaitForSeconds(1); // some time-consuming operation
handle.MarkDone();
}
}
Geting loadables
To specify what to load and in what order, override GetLoadables()
in CoreController or CoreProjectContext depending on the scope to which the loadable belongs.
Note
Loadables returned by the CoreController are loaded each time you change the scene, but loadables returned by the CoreProjectContext are only loaded once.
There are a lot of ways you can get your loadables. The fast method is to use injection directly.
using AlchemyBow.Core;
using AlchemyBow.Core.IoC;
using System.Collections.Generic;
[InjectionTarget]
public class MyCoreProjectContext : CoreProjectContext
{
[Inject]
private readonly SampleCoreLoadable sampleCoreLoadable;
protected override IEnumerable<ICoreLoadable> GetLoadables()
{
yield return sampleCoreLoadable;
yield break;
}
}
Most of the time this solution is fine (especially for CoreProjectContext), but you should also consider delegating the task to other objects to prevent controllers from becoming tightly coupled with loadables.
Another interesting concept is to use the dynamic collection binding feature - you can add your loadables to some collection by installers and then use the collection in the GetLoadables()
method (this approach can be even better with some kind of sorted / priority collection).
Loading progress
You can react to the loading process progress (for example, update your loading screen). To do this, override the CoreController.OnLoadablesProgressed(LoadablesProgress)
method:
using AlchemyBow.Core;
using AlchemyBow.Core.IoC;
using System.Collections.Generic;
[InjectionTarget]
public class MyCoreController : CoreController<CoreProjectContext>
{
protected override IEnumerable<ICoreLoadable> GetLoadables()
{
// ...
}
protected override void OnLoadablesProgressed(LoadablesProgress progress)
{
UnityEngine.Debug.Log($"{progress.loadableIndex}/{progress.numberOfLoadables}---{progress.loadable}:{progress.loadableCompleted}");
}
}
Note that this method is called twice for each loadable (not once if there are none). Project context loadables are included if they haven't been loaded previously.
ICoreLoadingCallbacksHandler
ICoreLoadingCallbacksHandler provides a mechanism for notifying objects when CoreController finishes loading or starts unloading.
using AlchemyBow.Core;
public class SampleCoreLoadingCallbacksHandler : ICoreLoadingCallbacksHandler
{
public void OnCoreLoadingFinished()
{
// For example:
// - load some data
// - subscribe events
}
public void OnCoreSceneChangeStarted()
{
// For example:
// - unsubscribe events
}
}
To receive callbacks, add subscribers to the dynamic List<ICoreLoadingCallbacksHandler>
binding:
using AlchemyBow.Core;
using AlchemyBow.Core.IoC;
using System.Collections.Generic;
public class SampleMonoInstaller : MonoInstaller
{
public override void InstallBindings(IBindOnlyContainer container)
{
var sample = new SampleCoreLoadingCallbacksHandler();
container.Bind(sample);
container.AddToDynamicCollectionBinding
<List<ICoreLoadingCallbacksHandler>, ICoreLoadingCallbacksHandler>(sample);
// Or with a shortcut:
// container.AddToDynamicListBinding<ICoreLoadingCallbacksHandler>(sample);
}
}
Warning
ICoreLoadingCallbacksHandler cannot be used in the project context.