public sealed class BehaviorJobAttributeMarks a behaviour type whose batch may have Update and LateUpdate dispatched across the job system instead of walked on the calling thread.
No guide page documents this yet — the page shows what the code says about itself.
As a annotation
- Valid on
- Class
Remarks
Item 3 of [04](../../../docs/plan/04-ecs-and-scripting.md) § Making it fast. Bucketing bought the cache locality — a batch is a contiguous T[] and the loop is monomorphic — and parallelism is a separate axis: ten thousand instances of one behaviour type is exactly the shape the job system exists for, and without this they run on one core.
⚠ What it promises is that this type's Update is safe to run on several threads at once, and nothing checks that at runtime. What checks it is VXS0417, an error: inside a marked type's Update or LateUpdate, the calls that reach unsynchronised store-wide or world-wide state — the lifecycle queues, the coroutine scheduler, structural change, and Get<T> of a managed component, which lazily allocates a slot in a table the whole world shares — are refused rather than left to fail on a busy machine. The attribute and the dispatch landed in one change with that analyzer for the reason HotPathAttribute records: an attribute naming an enforcement nobody wrote reads from a call site exactly like one that is checked.
⚠ Not inherited, and the bucket is the reason. A behaviour is bucketed under the static type at its Add<T> call site, and it is that closed generic which reads this. A subclass is a different bucket with a different Update, so it marks itself or it does not run in parallel — inheriting the mark would parallelise a body its author never offered.
⚠ An exception out of a dispatched batch arrives wrapped. The serial loop lets a behaviour's exception propagate as itself; the job system reports a batch that threw as a JobExecutionException around it. Nothing here unwraps it, because the wrapper is what says which of several threads the failure came off.
What it does not buy. A batch is dispatched at a sync point where no system is running, so this parallelises within a bucket and not a bucket against a system. Scheduling a behaviour's work against another system's needs an access declaration for behaviour types, which does not exist — [InferAccess] reads queries, and a behaviour reaches components through Get<T> and the transform façade instead.
Used by (2)
- BehaviorBucketVixen.Engine
- DispatchedVixen.Engine.Tests