Let’s say I have some code that can only run on the main thread, but is dependent on the result of a job. My understanding is the only way to make the main thread wait on jobs is to call JobHandle.Complete() - but if you call that, the main thread obviously won’t go on and continue scheduling jobs / doing whatever else it would normally do in the meantime.
So is the solution to put the main thread code in the last system that runs? If so, wouldn’t that mean that the code is delayed until ALL previously scheduled jobs are finished (since inputDeps is chained from system to system, if I understand it right)?
This seems like it must be a common pattern, especially now while there’s still a lot of main thread only code that we need to interface with, so I’m possibly missing something very obvious. Thanks for any insights!
If you create own system, and manually update, then there is in that system boolean status, which says if system runs, or is ready. Something like that. You can use it, to execute content of if statement.
System1 : JobComponentSystem
[UpdateAfter(typeof(System1))] // Or put an UpdateBefore on System1
System2 : ComponentSystem
and you’re done.
Execute your jobs in system1 pass the handle back, no need to complete or create a sync point. Schedule your main thread code in system 2.
As long as the queries in system2 depend on the components being modified in system1 the componentsystem will ensure the correct dependencies are complete before it runs.
Oh wow, I didn’t know it would actually delay the execution of a ComponentSystem, but I guess that makes more sense than every OnUpdate being executed sequentially as if they were all one big function.
Thanks so much, it’s end of day here but I’ll give it a go tomorrow!
@tertle is not that using update after/before will execute anyway every frame, even if depended system is running for more than one frame, or not running at all?
In my expariance, Update before / after will execute irrespectively, weather related system is running or not. It just keeps running order. But if related/ dependant system is not running, system with Update After/Before will run anyway.
Basically what will happen in case where JobA is to update after JobB, and JobB runs for more than 2 frames. Will JobA wait for 2+frames before execution?
Or JobA will execute every frame anyway, if JobB is already running over one frame?
A job can’t run ahead of its dependencies. So if JobB is dependent on JobA, it will wait for JobA to finish before starting. However, both SystemA and SystemB as well as many subsequent systems may be long done with their main thread OnUpdate routines by this point.
And in the case where JobB is not dependent on JobA, it should not matter which order the two jobs run.
This worked great by the way, thanks again @tertle ! I have some concerns about how this approach forces us to split tightly-coupled code into multiple systems but I guess that’s a tradeoff we have to live with
You generally don’t need to worry in a regular ComponentSystem about completion of prior jobs because accessing entities on the main thread will trigger completion of the relevant jobs. For example, a ForEach on the main thread completes all jobs touching relevant entities before it runs. Moreover, any structural change on the main thread completes all outstanding JobComponentSystem jobs.
In fact, you should be careful about ordering of your systems so that jobs don’t get completed sooner than you expected.
(So I’m not sure @tertle is correct: to my understanding, the completion of entity jobs is done as needed by individual ops on the main thread, not by the ComponentSystem merely updating.)
Hmm, what about entity access within a component system where the entities are not part of any registered query of the system? Like what if I just access entities through the entity manager that are touched by outstanding jobs, but no queries of the system conflict with those jobs? The jobs wouldn’t be completed before the update, but they would need completion before I touch the entities inside the update. Does access through the entity manager trigger the completion as needed, or is it our responsibility to register the appropriate queries with the system?