I have 4 JobComponentSystem systems, A, B C, and D. Which run in order A → B → C → D. A is the first system to run and D is the last. Not just out of my systems but out of all systems run in Update.
A calls Complete() on inputDeps.
B sporadically complains about D not being completed.
To test a theory I assigned the JobHandle that D returns to a static field, and called Complete on it in A. Sure enough errors go away B no longer complains.
I also thought ok maybe D jobs weren’t getting scheduled until the next Update for some reason. I added JobHandle.ScheduleBatchedJobs() at the end of D but no effect. It would be strange anyways if that was the case.
No idea what is going on but the hack works so not a huge deal. Each of the systems runs a chain of 2-4 jobs with RaycastCommand and and IJobParallelForTransform in the mix also. So getting a repro would likely take more time then it’s worth given I have a workaround.
Forgot to mention might be helpful. It was complaining about reading the length of a NativeHashMap in B’s OnUpdate. Where D has a job that writes to that same NativeHashMap.
Like I said I call Complete in A, so B complaining about something not completed from D in the previous cycle, shouldn’t happen. A is also marked as AlwaysUpdateSystem. The fact that if I Complete on that static reference makes this go away, means the jobhandle that D returns doesn’t have the same dependencies as the JobHandle that is passed to A.
So if we assume there is no bug in dependencies, then it might be that D’s jobs are just not getting run before A is called. Seems unlikely but I guess that’s possible.
We really need JobHandle to have more debugging options, like showing the dependency chains it has. Because you can create some fairly pathological patterns when you have systems that don’t always run. That has hit me before a few times with managing dependencies.
Ok ya I know what is happening, and I swear I’ve been bitten by this before.
Systems are only passed dependencies to components they declare. A isn’t passed dependencies that B needs to Complete on.
There should be some way to specify pass me all dependencies. Because not all dependencies in the game are component dependencies. Especially now with no recourse but to have a lot of hybrid code.
So you end up with situations like I have. B depends on A, But A is where I need to complete not B. Because that would force A’s jobs to just run on the main thread.