Runtime debug overlay

The runtime network debug overlay and its console commands.

Assumes you have finished quick-start.

One section below is generated, not typed. § Rows is generated from the kit's own row list, one line per row in the order the panel draws them (the two Validator rows' source reads "the overlay's log sink"), and the two bitmasks in § Commands are computed from EUKOverlaySection's bit order. The page is checked against that list cell by cell, so the table and the panel cannot drift.

How to read the brackets. A bracket after a statement says how it is known and on which engine: [source-read 5.x] — read in that engine's source; [measured 5.x] — observed by the kit's own tests on that engine; [unverified] — not yet confirmed.


What it shows

A small text panel in one corner of each local player's screen that answers why did that interaction not happen? while you play: which object you are focused on and why it is or is not usable, what request is in flight, what the server decided and why, who holds a lock and where you are in its queue, and which UK-VAL rule lines this machine has logged. Most lines are one named, documented value from a getter the kit already ships; the Header rows come from engine calls, and the Validator rows are derived from this machine's log. The panel adds no replicated property and no RPC, and it only reads — it never changes the state it shows.

Turning it on. Two switches, both needed:

  1. Tick Enable Debug Overlay — the setting bEnableDebugOverlay in Project Settings → Plugins → UK Interaction → Diagnostics. It is off by default; while it is off, UK.Overlay 1, UK.Overlay.Dump and UK.Overlay.Sections only log a line telling you to turn it on.
  2. Open the console and type UK.Overlay 1 (UK.Overlay 0 hides it again). Or tick Show On Start in the same settings group (Overlay.bShowOnStart) to have the panel up from the first frame — the only way to catch a UK-VAL line logged at BeginPlay.

The panel never takes input: it cannot be clicked, focused or tabbed to, and it adds no key of its own. If you want a key, bind one in your project to the console command.

The one-frame lag. The panel refreshes at a fixed rate (Overlay.RefreshHz, default 10 per second) from a tickable object, and the engine ticks those objects before the late tick group the kit's detection runs in. So a refresh shows the previous frame's focus and detection — a one-frame lag that is invisible at ten refreshes a second, and the reason a value you just changed can appear one frame late. [source-read 5.6 / 5.7 / 5.8]

Where it exists. The overlay is its own module, UKInteractionDebug, loaded on game clients (a listen host included) and in the editor, in every build configuration except Shipping and Test. It is absent from Shipping and Test builds, from a dedicated server (no local player, so no panel), and from the Lite edition; in those the UK.Overlay commands do not exist.

Settings (Project Settings → Plugins → UK Interaction → Diagnostics → Overlay):

SettingDefaultRangeWhat it does
bShowOnStartoff—Panel up from the first frame
RefreshHz101 – 30Refreshes per second
CornerTopLeftfour cornersWhich corner the panel sits in (the prompt is bottom-centre)
Opacity0.820 – 1Backing opacity
FontSize108 – 16Monospace point size — the lever if the panel is too tall
ZOrder10000 – 10000Draw order; above the prompt by default
EnabledSectionsall twelvebitmaskWhich sections are shown (§ Commands)
EventHistoryLines80 – 64Length of the event history; 0 removes it
ValidatorHistoryLines40 – 32Captured rule lines kept; 0 leaves only the count

A hand-edited value outside its range is clamped when it is read.

Cost. The measured cost (c_snapshot, about 60–70 µs per refresh on the development machine the kit is measured on, standing in for reference hardware, at 10 refreshes a second) covers building the snapshot and its change check only. The on-screen part of a refresh — writing the panel's text and Slate's layout and paint — is not measured yet, and while a hold or a lock reservation is running the panel's timers change every refresh, so the text is rewritten every refresh during those moments. Averaged over frames, that snapshot cost is about 11 µs per frame at 10 refreshes a second and 60 fps, inside the kit's 20 µs per-frame budget for the panel. [measured 5.8, advisory] The panel is off by default, so none of this is paid until you turn it on.

Commands

CommandWhat it does
UK.Overlay 0 / UK.Overlay 1Hides / shows the panel. The variable starts at -1, which means "not set — follow Show On Start".
UK.Overlay.DumpThe text alternative: everything the panel shows, as UK-OVL lines in the log — one line per row, taken now, whatever the refresh rate. Use it to paste the panel into a bug report or to grep a session log.
UK.Overlay.Sections <mask>Shows only some sections for this session. The mask is an integer, decimal digits only, 0–4095, one bit per section in the order of § Rows (Header is bit 0, Validator the last); anything else is rejected with a Warning. With no argument the command prints a hint.

While Enable Debug Overlay is off, only UK.Overlay 1, UK.Overlay.Dump and UK.Overlay.Sections log a line (telling you to turn it on) and do nothing else; UK.Overlay 0 logs nothing. A UK.Overlay value other than -1, 0 or 1 (for example UK.Overlay 5) logs a Warning whether the setting is on or off, and is read as -1.

While the game is paused, UK.Overlay 0 / UK.Overlay 1 take effect when it unpauses: the panel is refreshed by a tick that does not run while paused, so it keeps the last rows it drew. UK.Overlay.Dump works at any time and always reads the state now.

With every section on, the panel is taller than a 1080p screen at the default font size and clips at the bottom — which is where Lock and Validator sit. Two recipes trim it:

Triage — Header, Focus, Pending, Active, Events, Lock, Validator. Sized for a 1080p screen at FontSize 10 with every source present; if it still clips on yours, lower FontSize.

UK.Overlay.Sections 2675

Prompt — Header, Focus, Prompt, Input: for "why is there no prompt?".

UK.Overlay.Sections 387

Row grammar

Every row the panel shows is also one log line when you run UK.Overlay.Dump, in exactly this grammar — the panel and the dump carry the same text, byte for byte:

^UK-OVL ([A-Z][A-Za-z]+)\.([A-Za-z_][A-Za-z0-9_]*(?:\[[0-9]+\])?)=(.*)$

Group 1 is the section, group 2 the key (for counter rows the field's own name; for every row, § Rows' source column gives the line), group 3 the value. The value may itself contain =, so split on the first = after the key. Examples:

UK-OVL Focus.target=BP_Door
UK-OVL Pending.hold_s=2.00
UK-OVL Protocol.RejectedByReason=OutOfRange=2;Locked=1
UK-OVL Lock.stats_Admitted=—

Rows

Twelve sections, always in this order. history[i] and last[i] stand for one row per kept line, oldest first.

Section.keysourcemachine
Header.versionSource/UKInteraction/Public/UKInteractionConstants.h:189both
Header.netmodeengine:UWorld::GetNetModeboth
Header.playerengine:ULocalPlayer::GetControllerIdboth
Header.roleengine:AActor::GetLocalRoleboth
Header.refresh_hzSource/UKInteraction/Public/UKInteractionSettings.h:394both
Header.profileSource/UKInteraction/Private/Interactor/UKInteractorComponent.cpp:88both
Focus.stateSource/UKInteraction/Public/Interactor/UKInteractorComponent.h:292owner
Focus.targetSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:153owner
Focus.presetSource/UKInteraction/Public/Interactable/UKInteractableComponent.h:236owner
Focus.usabilitySource/UKInteraction/Public/Interactable/UKInteractableComponent.h:218owner
Focus.interactable_stateSource/UKInteraction/Public/Interactable/UKInteractableComponent.h:402owner
Focus.distance_cmSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:191owner
Focus.prompt_textSource/UKInteraction/Public/Interactable/UKInteractableComponent.h:240owner
Focus.denialSource/UKInteraction/Public/Interactor/UKInteractorComponent.h:233owner
Detection.TickCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:248owner
Detection.GatherCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:252owner
Detection.FocusChangedCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:256owner
Detection.OriginFallbackCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:260owner
Detection.RegisteredCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:265owner
Detection.OverlapHitsSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:269owner
Detection.PoolSizeSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:273owner
Detection.bPoolTruncatedSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:277owner
Detection.CandidateCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:281owner
Detection.RejectedByReasonSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:285owner
Detection.UsabilityCallsSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:289owner
Detection.LosTracesSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:293owner
Detection.LosBlockedSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:297owner
Detection.LosCacheHitsSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:301owner
Detection.SweepCountSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:305owner
Detection.DetectionMicrosecondsSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:309owner
Detection.BroadcastMicrosecondsSource/UKInteraction/Public/Interactor/UKDetectionTypes.h:313owner
Protocol.RequestsSentSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:250both
Protocol.AcceptedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:253both
Protocol.CompletedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:256both
Protocol.RejectedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:259both
Protocol.CancelledSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:262both
Protocol.LocalRejectedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:266both
Protocol.StaleResolvesSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:270both
Protocol.HoldMismatchCountSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:274both
Protocol.RetractionsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:277both
Protocol.RejectedByReasonSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:280both
Protocol.ReceivedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:285both
Protocol.ServerRejectedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:288both
Protocol.ServerRejectedByReasonSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:291both
Protocol.ThrottleViolationsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:294both
Protocol.ThrottleDroppedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:298both
Protocol.TargetUnresolvedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:302both
Protocol.EndIgnoredSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:306both
Protocol.HoldsCompletedSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:309both
Protocol.HoldsCancelledSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:312both
Protocol.ServerLosTracesSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:315both
Protocol.PendingSerialSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:321both
Protocol.PendingPhaseSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:324both
Protocol.ReleasedRecordsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:328both
Protocol.LastResolveLatencySecondsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:331both
Protocol.PredictedTickMicrosecondsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:341both
Protocol.ActiveSerialSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:347both
Protocol.LastOriginDivergenceCmSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:351both
Protocol.ValidationMicrosecondsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:355both
Protocol.ValidationLosMicrosecondsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:359both
Protocol.ValidationApplyMicrosecondsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:363both
Protocol.HoldTickMicrosecondsSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:367both
Pending.serialSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:382owner
Pending.targetSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:385owner
Pending.phaseSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:388owner
Pending.hold_sSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:391owner
Pending.elapsed_sSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:394owner
Active.serialSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:404authority
Active.targetSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:407authority
Active.holdSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:410authority
Active.hold_sSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:413authority
Active.elapsed_sSource/UKInteraction/Public/Protocol/UKProtocolTypes.h:416authority
Events.last_interactorSource/UKInteraction/Public/Interactor/UKInteractorComponent.h:541both
Events.last_interactableSource/UKInteraction/Public/Interactable/UKInteractableComponent.h:496both
Events.history[i]Source/UKInteraction/Public/Events/UKInteractionFunctionLibrary.h:86both
Prompt.PublishCountSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:292owner
Prompt.GlyphResolveCountSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:296owner
Prompt.WhyNotShownCountSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:300owner
Prompt.WhyNotDroppedCountSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:304owner
Prompt.bWidgetCreatedSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:308owner
Prompt.bWidgetOnScreenSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:312owner
Prompt.bTickerActiveSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:316owner
Prompt.LastDeviceKindSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:320owner
Prompt.LastPublishMicrosecondsSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:324owner
Prompt.visibleSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:84owner
Prompt.why_notSource/UKInteractionClient/Public/Prompt/UKPromptTypes.h:131owner
Input.bBoundSource/UKInteractionClient/Public/UKInputTypes.h:83owner
Input.bContextActiveSource/UKInteractionClient/Public/UKInputTypes.h:87owner
Input.bEnhancedInputComponentSource/UKInteractionClient/Public/UKInputTypes.h:95owner
Input.LastDeviceKindSource/UKInteractionClient/Public/UKInputTypes.h:105owner
Lock.policySource/UKInteraction/Public/Interactable/UKInteractionPreset.h:109both
Lock.holderSource/UKInteraction/Public/Interactable/UKInteractableState.h:79both
Lock.queueSource/UKInteraction/Public/Lock/UKLockTypes.h:50both
Lock.my_positionSource/UKInteraction/Public/Lock/UKInteractionLockComponent.h:79both
Lock.reservation_sSource/UKInteraction/Public/Lock/UKInteractionLockComponent.h:87both
Lock.stats_AdmittedSource/UKInteraction/Public/Lock/UKLockTypes.h:70authority
Lock.stats_QueuedNewSource/UKInteraction/Public/Lock/UKLockTypes.h:74authority
Lock.stats_QueuedRepeatSource/UKInteraction/Public/Lock/UKLockTypes.h:78authority
Lock.stats_LockedSource/UKInteraction/Public/Lock/UKLockTypes.h:82authority
Lock.stats_ExpiredSource/UKInteraction/Public/Lock/UKLockTypes.h:86authority
Lock.stats_PrunedInvalidSource/UKInteraction/Public/Lock/UKLockTypes.h:90authority
Lock.stats_ClearedOnDisableSource/UKInteraction/Public/Lock/UKLockTypes.h:94authority
Lock.stats_MaxQueueObservedSource/UKInteraction/Public/Lock/UKLockTypes.h:98authority
Lock.stats_ArbitrateMicrosecondsSource/UKInteraction/Public/Lock/UKLockTypes.h:102authority
Lock.stats_EndedMicrosecondsSource/UKInteraction/Public/Lock/UKLockTypes.h:106authority
Pickup.TakesSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:65authority
Pickup.AlreadyTakenRejectedSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:69authority
Pickup.RespawnedSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:73authority
Pickup.DestroyedSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:77authority
Pickup.DisabledByTakeSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:81authority
Pickup.RespawnSkippedAlreadyEnabledSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:85authority
Pickup.MarkerHealedSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:89authority
Pickup.MarkerAlreadyPendingSource/UKInteraction/Public/Interactable/Presets/UKPickupSubsystem.h:93authority
Validator.countthe overlay's log sinkboth
Validator.last[i]the overlay's log sinkboth

What each section means

Which machine this panel belongs to: the net mode (Standalone, ListenServer, Client), the local player's controller id, the pawn's role (Authority, AutonomousProxy, …), the kit version, the refresh rate and whether UK.Protocol.Profile is on (protocol.md § UK.Protocol.Profile). Read it first: every other row is a statement about this machine.

Focus

What the local interactor is focused on and what that object says about itself: its preset, its usability and state, the distance, the resolved prompt text, and the last reason a press was refused locally before anything was sent (Focus.denial, the reason On Interact Denied reported).

Which machine? On Interact Denied — Local machine.

Detection, Protocol, Pending, Active, Events

Detection is the interactor's detection counters, one row per field of FUKDetectionStats. Protocol is FUKProtocolStats: the client group on the player's own machine, the authority group on the server, and both on a listen host. Pending is the request this client has in flight and Active the interaction the server is running. Events is the last event on the interactor and on the focused object, each rendered the way events.md describes, followed by a short history (EventHistoryLines). The timing rows (…Microseconds) are filled only while UK.Protocol.Profile is on.

Prompt, Input

The sample prompt's counters and state — including bWidgetCreated / bWidgetOnScreen and the why-not line — and the input binding's state, both from the local player's own machine (prompt.md, input.md).

Lock

The focused object's lock (lock.md): the policy, the holder, the queue in order, your own place in it, the time left on a reservation, and — on the server only — the lock's counters, each keyed stats_<Field>. A client does not have the counters, so its panel shows — for every stats_ row, never 0.

Lock.my_position is 1-based: 1 is first in line, and 0 means you are not in the queue at all.

On a client, reservation_s is measured on the client's estimate of server time (AGameStateBase::GetServerWorldTimeSeconds()), which trails the server briefly; it can therefore read slightly above the lock's ReservationSeconds for a moment after a reservation starts. The server's own panel is exact. A client with no game state yet shows —.

Pickup

The pickup scheduler's counters. They exist on the server only, so a client's panel shows —.

Validator

The rule lines this machine has logged — count, then the last few (ValidatorHistoryLines) — with the same UK-VAL-NNN token the editor and the rest of these documents use, so you can search once.

The Validator row counts UK-VAL lines from the log of the machine the panel runs on. On a listen host that includes the authority-only checks (UK-VAL-026, -041, -101, -110 to -113). A remote client — of a listen or a dedicated server — never sees those; read them in the server's log. A dedicated server has no local player and therefore no panel. In PIE with Run Under One Process every instance shares one log, so a client window also counts the server's lines — that is PIE, not your shipped game.

The panel reads the log as it refreshes and does not wait for lines still being written, so it can trail the log by up to one refresh. UK.Overlay.Dump waits for the log first, so a dump is always current.

Placeholders

A row whose source does not exist on this machine shows — (an em dash): no lock component on the focused object, no authority, no focus, a pickup scheduler that is inactive on a client. A section whose source is missing shows its header with — in its first row — never a blank, and never a stale value left over from the last object you looked at. — means this machine does not know; 0 always means counted, and zero.

A section you turned off with EnabledSections is not drawn at all, so a hidden section and an empty one never look alike.

Known gaps

Recorded so you can read every claim on this page as narrowly as it was proven.

  • Engine coverage. The overlay is written for every supported engine with no version gates. In one line: "supported on 5.6–5.8; multiplayer end-to-end suite run on all three". The session tests that drive the panel end to end have run on the engines that sentence names as run, and on no other.
  • Nothing on the panel is pixel-tested. Every automated run is headless, so what is tested is the text — the same lines UK.Overlay.Dump writes. Font, colour, corner and opacity are not asserted by any test; the screenshot above is the on-screen record, taken in an editor session by hand.
  • Whether the triage recipe fits a 1080p screen is derived, not measured. It is sized for it at the default font size and sits on the margin; FontSize is the lever if it clips.
  • Split-screen. Two local players in one process each get their own panel and their own rows, which is tested. Where each panel lands inside its player's part of the screen has not been checked on screen.
  • The on-screen part of a refresh is not measured — only the snapshot is (§ What it shows › Cost).
  • Development builds only. The overlay is not in Shipping or Test builds, not on a dedicated server, and not in the Lite edition — by design, so it can never reach a player.