Priority events
Invocation
Choose normal, fast, safe, selective, and masked invocation patterns.
- Invoke
- InvokeFast
- InvokeSafe
- Masks
Choose the invocation shape that matches the path: normal, fast, safe, selective, or masked.
Invoking
Normal Invoke
Invoke visits active slots from 1 through 9.
CombatBus.Tick.Invoke();
CombatBus.HealthChanged.Invoke(currentHealth);
var report = new HitReport(origin, hitPoint, normal, targetId);
CombatBus.HitReported.Invoke(in report);Invoke is the standard all-slot invocation path. It drains queued off-thread subscription operations before dispatching and handles cancellation options. It does not isolate handler exceptions; a throwing handler can escape the call. Use InvokeSafe when you need ExceptionMode behavior and result details.
InvokeFast
InvokeFast is the optimized hot-path invocation.
CombatBus.Tick.InvokeFast();
CombatBus.HealthChanged.InvokeFast(currentHealth);
CombatBus.HitReported.InvokeFast(in report);Use it when:
- you are in a high-frequency path
- you do not need per-handler cancellation checks
- you trust the handlers not to throw
- you want the fastest all-slot dispatch after warmup
InvokeFast uses a direct dispatch path. Do not use it when you need exception isolation or detailed exception results. Prefer Invoke while learning, and move to InvokeFast when profiling says the event is hot enough to matter and the handlers are trusted.
InvokeSafe
InvokeSafe returns an AzInvokeResult.
AzInvokeResult result = CombatBus.HealthChanged.InvokeSafe(currentHealth);
if (!result.Success)
{
Debug.LogWarning(result.ToDetailedString());
}Use InvokeSafe for diagnostics, tooling, editor workflows, validation, and systems where you need result details.
Selective Invocation
Priority events can invoke only part of the slot set.
InvokeSlots
InvokeSlots accepts a bitmask. Bit 0 is slot 1; bit 8 is slot 9.
CombatBus.Tick.InvokeSlots(AzPriorityMasks.UpTo(3)); // slots 1..3
CombatBus.Tick.InvokeSlots(AzPriorityMasks.From(7)); // slots 7..9
CombatBus.Tick.InvokeSlots(AzPriorityMasks.Slot5); // slot 5 onlyFor payload events, the mask comes first:
CombatBus.HealthChanged.InvokeSlots(AzPriorityMasks.UpTo(3), currentHealth);
CombatBus.HitReported.InvokeSlots(AzPriorityMasks.From(7), in report);InvokePriorityAtLeast
InvokePriorityAtLeast(minPriority) invokes slots 1..minPriority.
CombatBus.Tick.InvokePriorityAtLeast(3); // slots 1, 2, 3
CombatBus.Tick.InvokePriorityAtLeast(5); // slots 1, 2, 3, 4, 5This helper exists on the no-payload AzPriorityEvent.
InvokePriorityAtMost
InvokePriorityAtMost(maxPriority) invokes slots maxPriority..9.
CombatBus.Tick.InvokePriorityAtMost(7); // slots 7, 8, 9
CombatBus.Tick.InvokePriorityAtMost(5); // slots 5, 6, 7, 8, 9This helper exists on the no-payload AzPriorityEvent.
InvokeSlot
InvokeSlot invokes exactly one slot.
CombatBus.Tick.InvokeSlot(5);
CombatBus.HealthChanged.InvokeSlot(5, currentHealth);
CombatBus.HitReported.InvokeSlot(5, in report);Important: full Invoke and InvokeFast refresh the occupied slot mask and drain queued off-thread operations. Single-slot invocation is best for main-thread-managed subscriptions where you know the slot is already current. If you rely on off-thread subscriptions, prefer Invoke, InvokeFast, or InvokeSlots so queued operations are drained first.
InvokeOnly and InvokeWhere
The no-payload AzPriorityEvent also exposes InvokeOnly and InvokeWhere.
byte[] slots = { 1, 5, 9 };
CombatBus.Tick.InvokeOnly(slots);
CombatBus.Tick.InvokeWhere(slot => slot <= 3 || slot == 9);Use masks for common fixed patterns. Use InvokeWhere when the slot decision is dynamic and easier to express as a predicate.
AzPriorityMasks
AzPriorityMasks provides constants and helpers for building slot masks.
Constants
AzPriorityMasks.Slot1
AzPriorityMasks.Slot2
AzPriorityMasks.Slot3
AzPriorityMasks.Slot4
AzPriorityMasks.Slot5
AzPriorityMasks.Slot6
AzPriorityMasks.Slot7
AzPriorityMasks.Slot8
AzPriorityMasks.Slot9
AzPriorityMasks.OddSlots
AzPriorityMasks.EvenSlots
AzPriorityMasks.None
AzPriorityMasks.AllHelpers
ushort early = AzPriorityMasks.UpTo(3); // slots 1..3
ushort late = AzPriorityMasks.From(7); // slots 7..9
ushort middle = AzPriorityMasks.Build(4, 6); // slots 4..6
ushort custom = AzPriorityMasks.Combine(
AzPriorityMasks.Slot1,
AzPriorityMasks.Slot5,
AzPriorityMasks.Slot9);
bool includesFive = AzPriorityMasks.ContainsSlot(custom, 5);Build(start, end) is order-agnostic:
AzPriorityMasks.Build(1, 3); // slots 1..3
AzPriorityMasks.Build(3, 1); // also slots 1..3