How-To: Performance Stat Widgets

Goal: an FPS/ping readout with optional graph, grouped in a container that shows/hides each stat from a settings value.

You supply the data
The widgets are display shells. FetchStatValue returns 0.0 until you override it - there is no built-in sampler in CrimsonUI or CrimsonCommon. Wire it to your own telemetry (or engine queries like GAverageFPS / GetNetDriver()->GetPing()).

1. One widget per stat

Subclass Crimson Perf Stat Widget Base (UCrimsonPerfStatWidgetBase, a passive UCommonUserWidget). Set StatToDisplay (an ECrimsonDisplayablePerformanceStat from CrimsonCommon - ClientFPS, ServerFPS, FrameTime, FrameTime_GameThread, FrameTime_RenderThread, FrameTime_RHIThread, FrameTime_GPU, Ping, PacketLoss_Incoming/Outgoing, PacketRate_Incoming/Outgoing, PacketSize_Incoming/Outgoing, Latency_Total/Game/Render, IdleTime). Override Fetch Stat Value (BlueprintNativeEvent, returns double) to produce the number, and drive your TextBlock from it (e.g. a property binding or a timer).

Open the shipped W_CrimsonSingleTextStat (/CrimsonUI/UI/PerfStats/) as the reference: StatToDisplay set in Class Defaults, the Fetch Stat Value override in the graph, and a bound TextBlock formatting the number. W_CrimsonSingleGraphStat is the same pattern plus a PerfStatGraph. Duplicate one and change StatToDisplay + the fetch logic.

For a graph, add a Crimson Perf Stat Graph (UCrimsonPerfStatGraph) named PerfStatGraph (optional BindWidget) and call UpdateGraphData(ScaleFactor) (BlueprintCallable) whenever you sample; GraphLineColor, GraphBackgroundColor, and GraphMaxYValue style it.

Verify
The number updates in PIE. If it reads 0.0 forever, your Fetch Stat Value override is not being hit - check the function override list.

2. Group stats in a container

Put the stat widgets inside a subclass of Crimson Perf Stat Container Base (UCrimsonPerfStatContainerBase). Three shipped containers in /CrimsonUI/UI/PerfStats/ are ready references: W_CrimsonPerfStatContainer_TextOnly, _GraphOnly, and _FrontEnd - the same stat set laid out with different StatDisplayModeFilter values. On construct (and whenever you call UpdateVisibilityOfChildren), the container asks GetStatDisplaySetting(Stat) for every child stat widget and applies the returned ECrimsonStatDisplayMode:

ModeEffect
HiddenWidget collapsed
TextOnlyShown when the container's StatDisplayModeFilter includes text
GraphOnlyShown for the graph variant
TextAndGraphAlways shown (default when you do not override)

Override Get Stat Display Setting (BlueprintNativeEvent) to read your project's user settings - e.g. a CrimsonSettings keyed value per stat - and call Update Visibility Of Children when the player changes them. Duplicate the container with different StatDisplayModeFilter values to build separate text-column and graph-column layouts from the same setting.

Verify
Toggling your setting between Hidden/TextOnly/TextAndGraph shows and hides each stat widget accordingly after Update Visibility Of Children runs.

See also

  • CrimsonSettings wiki - a keyed settings store that pairs naturally with GetStatDisplaySetting.