When using ECS singletons in a MonoBehaviour, it's important to wait until the World is ready before accessing the component data through World.EntityManager. Attempting to access the data before the World is ready can result in errors or unexpected behavior.
In the editor, this may still work if the entity scene is loaded but in the build it's completely not a reliable approach.
// Dangerous to use approach
public static T GetSingleton<T>() where T : unmanaged, IComponentData
{
var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
var query = entityManager.CreateEntityQuery(ComponentType.ReadOnly<T>());
var entity = query.GetSingletonEntity();
return entityManager.GetComponentData<T>(entity);
}
One way to solve this problem is to use a dependency injection (DI) framework such as VContainer and a task management library like UniTask. Here's how it works:
- Define the singleton component as usual.
- Create a specific system that waits for the singleton component to become available.
- Once the singleton component is ready, the system completes a task with the component data.
- The consumer class waits for the task to complete and retrieves the component result.
p.s. let me know if there are any mistakes in the code or there is a better approach with the single scene.
code is distributed under WTFPL license