Skip to content

Stratkit Map Notifications

Framework for transient, world-anchored UI shown on a shared world-space canvas - pool-backed, billboarded, screen-pixel scaled. Each notification kind lives in a consumer package (e.g. com.whs.map-notifications) and supplies its own prefab + spawner, fed by a *Request entity or a Producer<T> event.

Choosing a base class

  • AFloatingMapNotificationBehaviour - code-driven kinds with a fade-in / hold / fade-out envelope and an optional off-screen-edge fade. Subclass overrides UpdateContent() for per-frame text/icon updates; alpha composition is owned by this base. Recommended starting point.
  • AAnimatedMapNotificationBehaviour - Animator-driven kinds. A non-looping Lifecycle state drives a nested content CanvasGroup (fade-in / hold / fade-out, movement as animation); this base calls Finish() when the clip completes and adds an external dim/restore gate, SetExternallyVisible(bool), that fades the root alpha without ending the lifetime (e.g. gated by the zoom tier). Subclass overrides UpdateContent().
  • AMapNotificationBehaviour - direct base. Use for persistent button-closed kinds (set alpha = 1 in Setup; bind a button to RequestClose), or any kind whose lifecycle / fade story doesn't match the floating or animated envelopes. Subclass overrides OnLateUpdate() and owns alpha.

Adding a new notification kind

Mirror an existing consumer subfolder (e.g. com.whs.map-notifications/Runtime/ArmyCommand/).

Held / out-of-view kinds

A kind whose anchor can leave view holds the notification and shows a marker instead. MapNotificationPendingTag flags the held state; HeldNotificationRegistry<TKey, TPayload> (in Stratkit.MapNotifications.Core) is a keyed hold store - a per-key accumulator, a snapshot-safe reconcile, and a payload free-list - keyed by Entity (one anchor) or a position cell (a cluster). It is a plain managed class, not a generic ECS system. See the WHS Damage kind (per-army window) for a consumer.

Lifecycle

  • Spawn is two-step. MapNotificationSpawnHelper.Spawn(...) returns a pooled GameObject parented under the per-region canvas; the spawner then calls the subclass's strongly-typed Setup(...) (each kind's Setup signature differs, so a single-call shape isn't viable).
  • Push-close. Subclasses call protected Finish() themselves when they're done - no "is finished" predicate on the base. Finish is idempotent.

Gotchas

  • AFloatingMapNotificationBehaviour seals OnLateUpdate for envelope composition - subclasses extending it override UpdateContent(), not OnLateUpdate.
  • Default ComputeScale assumes RectTransform.sizeDelta is in natural screen pixels; prefabs without ContentSizeFitter must override.