How-To: First-Run Setup Wizard

Goal: walk a player through a short setup sequence once, on their first launch - language, gamma calibration, whatever else the game needs decided up front - and never show it again.

Prerequisites
A UI layer to push a screen onto. The wizard is entirely optional; nothing else in the plugin depends on it.

1. Create the step widgets

One Widget Blueprint per page, parented to UCrimsonFirstRunStep (itself a UCommonActivatableWidget). A step declares no properties of its own - it is a page with four hooks.

HookKindPurpose
K2_OnStepActivatedBlueprintImplementableEventThe page became visible. Start animations or auto-calibration here.
K2_OnStepDeactivatedBlueprintImplementableEventLeaving the page. Commit anything pending here.
CanAdvanceBlueprintNativeEvent, returns boolReturn false to block Next until the player has interacted. Defaults to true.
GetStepTitleBlueprintNativeEvent, returns FTextThe page name for the progress indicator. Defaults to empty.
Verify
Each step Blueprint compiles and overrides at least GetStepTitle.

2. Create the wizard widget

A Widget Blueprint parented to UCrimsonFirstRunWizard. In Class Defaults, fill Step Classes with your step classes in order - that array is the whole sequence, and adding a fourth page is a fourth entry and no graph edit.

Override K2_OnStepChanged (NewStepIndex, NewStep) and put NewStep into your layout container - removing the previous one first, or using a Common Activatable Widget Switcher, which deactivates the outgoing page and activates the incoming one for you.

Override K2_OnWizardComplete and K2_OnWizardSkipped to leave the screen.

Wire the navigation buttons: Button_Next OnClicked -> Go To Next Step, Button_Back OnClicked -> Go To Previous Step, Button_Skip OnClicked -> Skip Setup. Use Is At First Step to hide Back, and Is At Last Step to relabel Next as "Finish". Get Total Steps and Get Current Step Index drive a progress indicator.

Native hookOnDefault
NativeOnStepChanged(NewStepIndex, NewStep)UCrimsonFirstRunWizardfires K2_OnStepChanged
NativeOnWizardComplete()UCrimsonFirstRunWizardfires K2_OnWizardComplete
NativeOnWizardSkipped()UCrimsonFirstRunWizardfires K2_OnWizardSkipped
NativeOnStepActivated()UCrimsonFirstRunStepfires K2_OnStepActivated
NativeOnStepDeactivated()UCrimsonFirstRunStepfires K2_OnStepDeactivated
Why the native twins exist
The K2_ hooks are BlueprintImplementableEvent, so a C++ subclass cannot override them - the same reason UCrimsonSettingScreen has NativeOnRestartRequired. CanAdvance and GetStepTitle are already BlueprintNativeEvent, so a C++ step overrides their _Implementation directly.
Verify
Push the wizard by hand. Next walks the steps, Back is hidden on the first, and Next reads Finish on the last.

3. Show it on first launch

Completion lives in the CrimsonSettings.FirstRun save slot (user index 0), a UCrimsonFirstRunState holding one bSetupCompleted flag. HasCompletedSetup() is a BlueprintCallable static that reads it.

In your main menu's Event On Activated (or Event BeginPlay for a test): Has Completed Setup -> Branch (False) -> Push Widget To Layer Stack (Layer = your Menu layer tag, Class = your wizard Blueprint).

Guard it with a "have I offered this already" boolean if the menu can be activated more than once.

bAutoSkipIfCompleted is a backstop, not the check
With bAutoSkipIfCompleted on (the default) the wizard deactivates itself on activation if setup is done, so it is safe to always push it. Asking HasCompletedSetup() before pushing is still the better call in a menu: a widget that is pushed and then deactivates on the same frame moves the layer stack and takes focus off whatever the player was looking at.
Finish records completion. Skip does not.
FinishSetup() writes the save slot; SkipSetup() deliberately does not, so a skipped wizard is offered again next launch. Deleting Saved/SaveGames/CrimsonSettings.FirstRun.sav re-arms it, which is how you test the flow repeatedly.
Verify
Delete the save file, launch, and the wizard appears. Finish it, relaunch, and it does not.

4. Make Skip a deliberate act (optional)

SkipSetup() has no guard of its own - the plugin does not decide how a player is asked to confirm leaving setup. The pattern worth copying:

  1. Give the Skip button its own hold Input Action rather than reusing the shared UI Back action. CommonUI reads a hold duration from the action's UInputTriggerHold and nowhere else, so putting that trigger on the shared Back action would turn every Back press in the game into a hold.
  2. Map that action to the same keys Back answers on. Holds are processed before normal input and consume the key, so while the wizard is the active root a held press reaches Skip and a tapped one reaches nothing. Releasing early cancels silently.
  3. On completion of the hold, open a confirmation dialog rather than skipping outright, and call SkipSetup() only on a confirmed result - deferred a tick, so leaving the wizard does not race the modal's teardown.
The hold needs a CVar
Add CommonUI.bEnhancedInputDynamicallyResolveHoldKeysForInputAction=1 to Config/DefaultEngine.ini. With it off - the engine default - the action router registers every Enhanced Input action as press-only no matter what triggers the asset carries, and the hold silently never happens.

Do not also set bRequiresHold on the button: that flag rejects any click while hold progress is below 100%, which kills the mouse click too. A mouse click on Skip should go straight to the dialog, which is what you want from a pointer.
Reference implementation
(CrimsonCore - requires all Crimson plugins) UCrimsonCoreFirstRunWizard with W_FirstRunWizard (/CrimsonCore/UserInterface/Settings/Wizard/) is a complete worked example of everything on this page: three steps in a UCommonActivatableWidgetSwitcher, progress pips built from GetTotalSteps(), bound CommonUI input actions on all three navigation buttons, and the hold-to-skip flow above. Its Blueprint supplies layout and nothing else.

See also

  • How-To: Brightness & Safe Zone Calibration - the screen a gamma step usually embeds.
  • API Reference -> Presentation - the full wizard and step surface.