CrimsonSettingsv1.0Coming to FabPersonal $24.99 · Professional $49.99
Join the Discord

A data-driven settings framework: take a complete Video / Audio / Mouse & Keyboard / Gamepad / Gameplay menu straight out of the box, or declare your own options in a data asset and persist them per player with zero glue.

Framework · Settings · Unreal Engine 5

The settings menu every game needs. Declared in data, not code.

A Crimson port of Epic's GameSettings architecture. Call five builders for a complete options menu with nothing authored, or declare your own in a data asset and tick one box to persist them per player. Search, presets, profiles, live preview, key rebinding and a first-run wizard ship in the box.

Why CrimsonSettings

Declare, persist, present: three layers that stay independent, so adding an option is a data-authoring task, not a plumbing one.

A complete options menu, nothing authored

Five builders produce Video, Audio, Mouse & Keyboard, Gamepad and Gameplay tabs: resolution, quality presets, HDR, frame-rate limits, volume mix, sensitivity, language, a rebind list per device. Each returns its collection, so adding your own row to a shipped tab is one call.

Options are data assets, not code

Author sections and entries (scalar sliders, discrete selectors, action buttons) in a UCrimsonSettingsDataAsset with its own tree editor: reorder, duplicate, and duplicate-DevName validation while you author. A Blueprint UCrimsonSettingRegistry turns the asset into live settings with one Populate From Data Asset call.

Persist per player with zero glue

Tick Persist To Shared Store and an entry's value saves into a Key → value store on the per-player save: no getter, no setter, no delegate. UCrimsonSharedSettingsSubsystem loads it, auto-saves on a debounce and broadcasts OnSettingChanged. Machine-tied state like resolution goes to UCrimsonSettingsLocal instead.

Or bind straight to game code

When a setting must drive live state, like a volume or a quality preset, handle K2_BindSetting and wire the _BP value classes' get/set delegates to your functions. In C++, UCrimsonSettingValueScalarDynamic resolves reflected getter/setter paths for resolution, scalability and gamma. Persisting and binding are independent choices.

Key rebinding, scoped per device

Rebindable actions come straight from Enhanced Input's UPlayerMappableKeySettings, no second list to maintain. Keyboard and gamepad get independent rows per action, with primary/secondary pills and reset-to-default. One setting picks full names, glyphs or abbreviations for every pill. Chord capture comes with CrimsonCore.

A CommonUI screen with the AAA flow

UCrimsonSettingScreen and UCrimsonSettingPanel bring search, tag filtering, dirty/default indicators, conflict warnings and performance-impact badges. On top: one-click presets, named profiles that snapshot every setting, live preview that commits only on Apply, keep/revert confirmation countdowns, a restart-required hook, a hardware benchmark and an optional first-run wizard.

A closer look

From an empty project to a persisting settings screen

Enable the plugin and point GameUserSettingsClassName at UCrimsonSettingsLocal in DefaultEngine.ini. After that it is data: author a data asset, populate a Blueprint registry from it, subclass UCrimsonSettingScreen and push it onto a UI layer.

  • The .ini line is the one step with no in-editor equivalent, and the plugin asserts without it
  • Tick Persist To Shared Store on each entry and values survive relaunch per player, nothing else wired
The in-game settings screen on the Video tab: Graphics Quality rows with 3D Resolution and Quality Presets marked Modified, a description panel for the selected setting, and Apply, Cancel and Defaults along the bottom

Any plugin can add settings without touching CrimsonSettings

The keyed store holds opaque Key → value pairs, so exposing another system's options is pure data authoring. Neither plugin gains a dependency on the other: CrimsonSettings never names a camera or gameplay concept.

  • Give each entry a namespaced Storage Key like Gameplay.AimSensitivity
  • A consumer module that sees both plugins reads the keys and applies them
  • Re-apply on OnSettingChanged so live edits take effect

The Apply flow players expect from a shipped game

With live preview on, dragging a slider updates the UI but commits nothing until Apply. Cancel's rollback comes free from the change tracker.

  • Flag resolution or display mode Requires Confirmation and a keep/revert countdown fires after Apply, reverting on timeout
  • Restart-required settings raise K2_OnRestartRequired for your banner

Calibration the player judges live

The Video tab ships two action rows: a full-screen gamma screen and a title-safe frame screen. Both adjust live on the mouse wheel and gamepad right stick, and Done writes through the registry so Apply lights up. You author the Widget Blueprints; the behavior ships.

  • Gamma is clamped 1.0 to 3.0, wider than Lyra's slider on purpose
  • The left stick stays with CommonUI navigation, so Back and Done remain reachable on a pad
  • On Windows the safe-zone row hides itself, because the platform reports a zero title-safe margin

Performance stats on the HUD, picked per stat

With CrimsonCore, one call hangs a Performance Stats page under Video → Display: eighteen stats, each set to None, Text Only, Graph Only or Text and Graph, and the HUD readout follows the choice while the menu is still open.

  • CrimsonCore ships the page: call AddPerformanceStatsPage from your registry
  • Standalone, hang your own page under any ready-made tab with K2_RegisterSettingInParent
  • The stat widgets themselves come from CrimsonUI

Technical details

Engine
UE 5.8
Tested platforms
Windows
Blueprint-ready
Yes
C++ required
No
Network replicated
No
Dependencies
CommonUI, EnhancedInput, AudioModulation

Frequently asked questions

Do I need C++ to use it?
Almost never: options are authored in a data asset, the registry and screen are Blueprint subclasses, the five default collections are Blueprint-callable, and binding a setting to game code happens through K2_BindSetting delegates. Two exceptions worth knowing before you buy: registering the GameUserSettings class is a DefaultEngine.ini line with no in-editor equivalent, and the advanced tier (Dynamic value classes with reflected data sources for engine-level settings) is C++. For keybind glyphs the docs also recommend one UCommonActionWidget subclass so a pill can pin itself to a device and read the Enhanced Input user settings while a menu is open.
Does it work in multiplayer?
Settings are a client-owned preference concern, and the framework treats them honestly as one: the screen and the per-player keyed store run on the owning client, with UCrimsonSettingsShared saved per local player, and nothing in either storage class replicates. Where a preference affects gameplay, send it to the server through your own validated path; you shouldn't drive authoritative gameplay from a client's preference value, and the plugin doesn't pretend otherwise.
Does it depend on other Crimson plugins?
No. CrimsonSettings builds and runs on its own with three engine plugins: CommonUI, EnhancedInput and AudioModulation. The screen pushes onto whatever UI stack you run, and the shipped keybind rows rebind plain keys through Enhanced Input's user settings.
What does CrimsonCore add?
CrimsonCore, the free integration layer from the Crimson Discord, joins CrimsonSettings to the rest of the suite: modifier-chord capture and chord-aware conflicts on keybind rows (with CrimsonInput), the Performance Stats page and the per-stat choice a HUD readout follows (with CrimsonUI), and mapping the gamepad sensitivity presets onto CrimsonInput. Without it, each has a public hook: KeybindingSettingClass and the keybind row virtuals, K2_RegisterSettingInParent for extra pages, and the UCrimsonSettingsShared getters.
Can other plugins or my game add settings without modifying CrimsonSettings?
Yes, that's the point of the generic keyed store. CrimsonSettings never gains a typed field for your option: you author an entry with a stable Storage Key, tick Persist To Shared Store, and read it back by name through UCrimsonSharedSettingsSubsystem. A consumer module that depends on both plugins applies the values, which is the only place the two names ever meet.
How stable are the setting names?
Treat a DevName the way you would a database column. It is the identity used by the keyed store's storage key, a saved profile's map, and a preset entry. Renaming one after players have saved settings orphans every value stored under the old name, and nothing migrates it for you. The framework does make collisions loud: duplicates are flagged in the asset editor while you author and asserted by the registry at runtime.

Ship the settings menu, not the settings plumbing

Author a data asset, populate a registry, push the screen, and you have persisting per-player options in a sitting. Then layer in presets, profiles, preview, and confirmation as your game grows.

Pricing

CrimsonSettings is sold on Fab under Epic’s two standard licenses. Both include the full plugin, source, and updates.

Personal$24.99For individuals & teams under $100K revenueComing to Fab. Join the Discord
Professional$49.99For companies over $100K revenueComing to Fab. Join the Discord