Skip to content

Blueprint result notifications ​

A short notification draws attention to a completed action without taking focus from the player. InterfaceForge supplies a bounded local-player queue and an ordinary replaceable IFEntry body. Your gameplay system decides when an action succeeds. The UI queue does not execute or validate gameplay commands.

The queue uses Unreal's local-player subsystem lifetime, matching its owning player rather than a single global HUD. See Epic's ULocalPlayerSubsystem API and subsystem Blueprint access. InterfaceForge's queue and reading-time behavior below are its own public contracts, verified against the installed engines.

The Outpost example posts Road secured / 40 supplies recovered. only after its patrol completes. Emberwatch posts Party restored / Ember Ward is active. after Ward succeeds and Watch restored when Kindle reaches the hearth. These are brief results; the persistent objective, resource and status models remain available in the HUD.

First working result ​

  1. Create the owning player's root with Get Local Player Subsystem → IFLocalPlayerSubsystem → Create Root. Use IFRootLayout or a Widget Blueprint derived from it with an empty Designer tree to retain the native layers.
  2. From the same PlayerController, use Get Local Player Subsystem and select IFNotificationSubsystem.
  3. On your successful-action event, call Post Notification, supplying Title and Message. The return value is a notification GUID; save it if the action needs to dismiss or update this result.
  4. Play. The default passive card appears above the HUD/menu and below dialogs, then disappears after four seconds of visible UI time. It does not move focus, accept clicks or create a separate window.
flowchart LR
    A[Your action succeeds] --> B[Get Local Player Subsystem: IFNotificationSubsystem]
    B --> C[Post Notification]
    C --> D[GUID for dismissal]
    C --> E[Public root presents IFEntry body]

Expand the advanced pins for Duration, Key, Scope, and Entry Class. Duration must be finite and positive; accepted durations are clamped to 0.25–60 seconds. Both empty texts, missing custom data, an invalid owner or an explicit class that does not implement IFEntry return an invalid GUID. Do not treat an invalid GUID as a successfully queued message.

Replace the appearance in Blueprint ​

Create a Widget Blueprint based on IFEntryWidget. Add your own Designer tree using IFSurface, IFText, images or other UMG controls. The example's saved WBP_ForgeNotification uses an accent title and body text in a compact horizontal ribbon.

In On Entry Refreshed:

Entry Data → Cast To IFPresentationData → Title / Detail → SetText on your title and message controls.

In On Entry Released, clear presentation text and stop any timers or animation work you started. IFEntryWidget binds Notify Data Changed and releases its old model subscription through the same lifecycle used by journal and command entries. A later Notify Data Changed on the live model invokes refresh without creating another notification.

Choose your body class in your root Blueprint's Default Notification Entry Class, or override Entry Class on an individual post. The saved WBP_ForgeRoot and WBP_EmberRoot use the same body with different Notification Dock values. Their owning example controllers expose Root Class. No plugin source edit is needed to replace either root or the body.

To change the live layer's Notification Entry Class, call Refresh Notification Presentation afterward. It releases the current body and reconstructs it on the next UI tick with the same model, GUID and remaining reading time. Register Entry Host performs this refresh automatically when the layer is already registered. A per-post Entry Class override continues to take precedence over the layer default.

For custom presentation data, call Post Notification Data with your UObject and an entry class that understands it. An ordinary Widget Blueprint may implement IFEntry directly instead of inheriting IFEntryWidget; it must implement Initialize Entry and Release Entry, including its own binding cleanup. The built-in card expects IFPresentationData, so select your compatible class when posting another model type.

Keep the body passive. Put interactive choices in a screen or dialog, where CommonUI can route accept/back and restore focus. Do not put essential actions inside a notification that intentionally ignores hit tests.

Updates, capacity and owner lifetime ​

Post Notification with a nonempty Key and the same Scope coalesces an existing record: it keeps that GUID and queue position, replaces its data/entry and resets reading time. Scope=None matches only another unscoped record. Empty keys always create distinct records. The old visible body receives Release Entry before replacement; coalescing does not emit On Notification Ended.

The default capacity is eight, including the visible record. Set Queue Capacity clamps to 1–32 and trims pending records. On overflow, the visible result is preserved and the oldest pending one ends with Overflow. At capacity one, a new record cannot displace an already visible result and its post returns an invalid GUID. Before any record is presented, the oldest queued one may be discarded. This finite queue is for attention, not a persistent event history.

Use a gameplay adapter, quest or screen object as Scope. The scope reference is weak and does not retain that owner. The queue retains its Data until the record ends; custom models should use weak gameplay references when needed rather than retain actors through the model. Call Dismiss Scope when an expedition or interaction ends even if its provider object remains alive. The examples do this on return to the main menu. Other owners' notifications survive that scope cleanup.

Dismiss Notification returns true only when its GUID was present. Subscribe to On Notification Ended for Expired, Dismissed, Scope Ended, Overflow, Invalid Entry, or Root Removed. Records are removed before the event; dismissing the same GUID again returns false. Clear Notifications ends all this player's records with Root Removed and rejects posts made from those end callbacks, preventing a flow cleanup from creating another stale message. The same guard applies during capacity trimming. An overflow callback during an ordinary post may fill the freed slot; the incoming post then returns invalid instead of recursively evicting callback-created records.

Reading time, dialogs and motion ​

The public root drives notification time through its UI tick, including while the game world is paused. A modal dialog or an active screen-stack transition collapses the notification layer and freezes visible reading time. Pending records do not count down before presentation. Weak-scope cleanup still runs while a modal suppresses display. If there is no registered presenter, records wait rather than silently expire.

The default fade uses the current theme's Transition Seconds, capped to one second. The presented Reduced Motion preference removes that fade. Get Remaining Seconds, Get Active Notification Id, Get Notification Data, and Get Notification Count expose the current state for your own extensions. Duration is not derived from world gameplay time.

Positioning and custom roots ​

Notification Dock is a normalized anchor within the root's safe area; the native layer aligns its body to that point horizontally centered and vertically downward. Notification Width is clamped to 120–600 layout units and at most 80% of the allocated player width. These defaults are copied into the layer during root construction. To change the live presenter, use Get Notification Layer and set its Dock or Preferred Width. Inspect the result at your largest UI/text preferences.

Reserve a lane in your own HUD rather than covering critical information. Outpost uses dock Y=0.28 and begins its lower panels at Y=0.46. Emberwatch uses Y=0.36 and begins its action/context areas at Y=0.54. Both root assets use width 600. A complete quest playthrough exposed a wrapped result overlapping the previous context position at Y=0.48 at maximum text/UI scale; the saved context anchor now leaves additional clearance. The current clearance verification is recorded in the acceptance record. Arbitrarily long or localized messages need your own wrapping/layout policy; use a contextual screen or journal for long explanations. A viewport bounds check cannot certify that an overlay leaves other information readable.

A root with a custom Designer tree owns its layout. Add an IFNotificationLayer above HUD/menu content and below the modal stack, then call Register Notification Layer on the IFRootLayout, passing that layer. Its owning player must match the root. The root retains the presenter, handles modal/transition suppression and clears/unregisters it when removed. Passing None explicitly unregisters it; a removed root rejects re-registration. Do not bypass the root with subsystem-only registration when relying on its cleanup. The saved WBP_ForgeFlowRoot demonstrates this actual public Blueprint graph; see Blueprint customization.

In a layer with a custom Designer tree, add a content container and call Register Entry Host; alternatively name the container EntryHost. An optional SizeBox named NoticeBounds receives the native width/dock behavior when it is a Canvas child. Otherwise your Designer tree owns sizing/placement.

Troubleshooting and verification ​

No result: check that the post returned a valid GUID, the correct local player owns the presenter, a root is alive, the body implements IFEntry, and a custom layer has an entry host. A dialog or transition intentionally postpones presentation. Stale message after returning: pass a Scope and call Dismiss Scope as your flow ends. Incorrect model text: check the body class and refresh graph, including whether the cast succeeded. Overflow: coalesce repeated status reports or change capacity; use a separate history model when every event must be retained.

Notification runtime evidence records actual source/cooked results and limits. Tests use Win64 UE5.6.1 DX11 rendering, synthetic Slate command/back input and programmatic lifecycle checks. They do not prove physical controller/touch behavior, split-screen, arbitrary localization, audibility or complete product readiness.

UIForge v0.1.0 · Blueprint and C++ development documentation.

Enlarged documentation image

Enlarged documentation image