I am using singleton components for global properties that I want to use within an IJobEntity.
I can write var singleton = SystemAPI.GetSingleton<MySingleton>(); , and then the lambda can capture this when I write an Entities.ForEach (or whatever other method you want, eg set it as a field on a IJobEntity). However, if another job writes to MySingleton, there is a dependency conflict where I must wait for the other job to complete before running GetSingleton on the main thread. Is there something analogous to GetSingleton(Dependency) that would allow me to delay getting of singleton, and perhaps get a RefRO to it? The other alternative I can do is create Native arrays of unit length to get the singleton in a delayed job, but this seems extremely cludgy. Thanks!
#Best practice for getting a singleton IDataComponent for use within IJobEntity
1 messages · Page 1 of 1 (latest)
Hmm, maybe I have found a bug. The manual claims:
For example, a call like SystemAPI.GetSingleton<MyComponent>() queries whether there is only one entity that matches the given criteria, and if so, gets the component MyComponent. It does this without asking the job system to complete all jobs that use MyComponent.
This is a useful alternative to EntityManager.GetComponentData, which syncs data. For example, when you call EntityManager.GetComponentData<MyComponent>, all jobs that write to MyComponent complete.
and yet I find my singleton access throws errors:
InvalidOperationException: The previously scheduled job AdvanceStateAfterStateHandlingSystems:AdvanceStateAfterStateHandlingSystems_41688D8C_LambdaJob_0_Job writes to the ComponentTypeHandle<AtomEngine.Sequence.SequenceState> AdvanceStateAfterStateHandlingSystems_41688D8C_LambdaJob_0_Job.JobData.__stateTypeHandle. You must call JobHandle.Complete() on the job
SystemAPI.GetSingleton<T> does not complete dependencies
If you are writing to the singleton in a job, you must call state.CompleteDependency() beforehand
Cheers @civic canopy ! Do I call CompleteDependency on the job handle (ie, I need to retain or otherwise access a handle to the dependent job from another system), or through the singleton component API? The line that throws the exception is:
if (!SystemAPI.TryGetSingleton<LaserCoolingGlobals>(out var globals))
return;
so I have no access to the component itself
(looks like via EntitiesManager.CompleteDependencyBeforeRO?)
Is there perhaps a cleaner method for a general problem of running an IJobEntity with a query over MyComponent but also requiring read access to MySingletonComponent? (For example, to store globals that control properties of a calculation performed over multiple entities)
(For context: I'm upgrading a project from entities pre-1, and systems are now truly stateless so the update guide wants me to move system-wide properties into Singletons. But before I could rely on lambda capture of a read-only property/field from the system, and the workflow with singletons seems quite painful by comparison. My kind of example is for a float factor that contains the global strength of a calculation, for instance, which previously I could stash on my system and now must be a singleton queried alongside the entity foreach)