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 overridesUpdateContent()for per-frame text/icon updates; alpha composition is owned by this base. Recommended starting point.AAnimatedMapNotificationBehaviour- Animator-driven kinds. A non-loopingLifecyclestate drives a nested contentCanvasGroup(fade-in / hold / fade-out, movement as animation); this base callsFinish()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 overridesUpdateContent().AMapNotificationBehaviour- direct base. Use for persistent button-closed kinds (setalpha = 1inSetup; bind a button toRequestClose), or any kind whose lifecycle / fade story doesn't match the floating or animated envelopes. Subclass overridesOnLateUpdate()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 pooledGameObjectparented under the per-region canvas; the spawner then calls the subclass's strongly-typedSetup(...)(each kind'sSetupsignature 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.Finishis idempotent.
Gotchas¶
AFloatingMapNotificationBehavioursealsOnLateUpdatefor envelope composition - subclasses extending it overrideUpdateContent(), notOnLateUpdate.- Default
ComputeScaleassumesRectTransform.sizeDeltais in natural screen pixels; prefabs withoutContentSizeFittermust override. - A damage number is counted only for an update where nothing but damage changed the army: the unit count moved by exactly the casualties the server reports. An update with a split, a merge or a reinforcement counts nothing.
- A removed army counts as killed only when the server's
ArmyDestroyed(own army) orEnemyArmyDestroyed(enemy killed by the player's army) event names it. An enemy killed by an ally's army shows only the in-window loss.