public sealed class BehaviorJobAnalyzerReports work inside a [BehaviorJob] batch that several threads cannot do at once.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
The half that makes the dispatch safe. docs/plan/04-ecs-and-scripting.md § Making it fast, item 3 asks for behaviour batches dispatched across the job system. What that section spends its length on is the blocker: a behaviour declares no access set, and — more immediately — its own convenience API reaches state the whole store shares. Enabled queues into a plain List<Behavior?>, Destroy() and Run(coroutine) do the same to their own queues, and none of it is synchronised, deliberately, because the lifecycle is drained on one thread. Inside a dispatched Update that is a data race rather than a slow path.
⚠ And the least visible member of the set is Get<T> of a managed component. Nothing at the call site says so: the world resolves a managed cell through StoreFor<T>(), which can resize the world's table and allocate a row's slot, so two behaviours reading the same managed component for the first time race each other. The read half of that was fixed — Read<T> and TryGet<T> resolve without writing — which is why this rule names Get<T> and not Read<T>: what is left is a write to world-wide state wearing a getter's face.
What it reads is the two bodies that are dispatched — the marked type's Update and LateUpdate, and the lambdas and local functions inside them — and nothing further down. ⚠ That bound is stated because it is the same one VXHP0001 states about itself: a helper method two calls away can queue a lifecycle change and this will not see it. Widening it to every method of a marked type would be worse than the gap, because Awake and OnEnable run on the drain thread where every one of these calls is correct.
An error, not a warning, and unlike its siblings it has no #pragma story. The escape from this rule is to take [BehaviorJob] off the type, which costs a batch its parallelism and nothing else. A suppressed race is a build that runs ten thousand instances across eight threads into an unsynchronised list.
Fields and properties (3)
public const string RaceDiagnosticIdThe id reported for shared state touched inside a dispatched batch.
public const string TargetDiagnosticIdThe id reported for [BehaviorJob] on a type no bucket will ever hold.
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnosticsReturns a set of descriptors for the diagnostics that this analyzer is capable of producing.
Methods (1)
public override void Initialize(AnalysisContext context)Called once at session start to register actions in the analysis context.
Used by (1)
- BehaviorJobRefusalTestsVixen.Engine.Generators.Tests