A Settings Screen in UE5: Change and Save Window Size, Quality, and Music Volume

Created: 2026-07-20Last updated: 2026-09-06

Build a settings screen in UE5 for window size, quality, and music volume. Sorts out applying and saving Game User Settings and reading back a volume SaveGame, through to settings surviving a relaunch.

You want the game window a bit smaller. It runs heavy, so you want lower quality. You want the music a little quieter. A settings screen is where players choose the state that suits them.

But placing dropdowns and sliders does not change the game's settings. The screen's job extends to applying the value chosen in the UI and being able to restore it on the next launch .

This article builds a small three-item settings screen using Game User Settings for display and a SaveGame for music volume.

A settings screen choosing window size, quality, and music volume, carrying the choices into the next launch

What You'll Learn

  • Why display settings and volume are saved in different places
  • What Set and Apply each change
  • How to apply and save Game User Settings
  • How to confirm settings survive a relaunch

What We Build

  • Choosing window size and quality and applying them with "Apply and save"
  • Comparing music volume with a slider and saving it from the same button
  • Relaunching the game and confirming display settings and volume come back

This assumes you have created Blueprint variables and functions and know the Widget placement and button events from UMG Basics. The hands-on is a Windows Standalone Game exercise showing the settings screen from launch.

Sponsored

Display settings and volume save to different places

Game User Settings is UE's standard settings object holding resolution, display mode, quality, and more. In Blueprint you fetch it with Get Game User Settings . You do not create one; pass the returned object to each setting node's Target.

Saving display settings normally writes to a settings file called GameUserSettings.ini , which the game loads at launch. You avoid building a resolution SaveGame class or your own file I/O from scratch.

The standard Game User Settings, however, has no "music volume" entry. For that we prepare our own variable and save it to a SaveGame , a container whose contents you decide.

What we want to keepWhat it applies toWhere it is saved
Window size and qualityGame User SettingsGameUserSettings.ini
Music volumeThe playing Audio ComponentA volume SaveGame

The same "Apply and save" button calls both save paths. One settings screen visually does not mean everything saves to the same place.

An Audio Component controls a playing sound. To change our music's volume, we specify that component.

One Apply and save button splitting into Game User Settings for display and a SaveGame for music volume

Progress data can use SaveGame too, but keeping volume separate from adventure save slots is easier to handle. Starting a new game then carries over the volume the player chose.

What Set and Apply each change

Display settings split into specifying values and applying those values to the game .

NodeWhat it does
Set Screen Resolution , etc.Changes a value held by Game User Settings
Apply SettingsApplies the settings to the game and saves them
Save SettingsSaves the setting values. Also called inside Apply Settings

Passing 1280 x 720 to Set Screen Resolution does not finish switching the window to that size. Call Apply Settings at the end.

Apply Settings both applies and saves. There is no need to add Save Settings right after it. Apply Settings official reference, Save Settings official reference

Here we keep display settings in dropdowns and call Set and Apply together when "Apply and save" is pressed. That avoids the screen switching repeatedly while choosing.

Passing the resolution set with Set to Apply Settings, which both applies it and saves it to a file

Choosing window size and quality

Match the display mode, not just the resolution

Resolution is the pixel width and height drawn. 1280 x 720 is 1280 across and 720 down. In Blueprint you use an Int Point grouping two integers, with X for width and Y for height.

At the same resolution, the display mode changes how it looks.

ModeHow it uses the screen
WindowedA framed window. What we use for size changes
Windowed FullscreenA frameless window using the whole desktop
FullscreenFullscreen. Supported resolutions and switching depend on the environment

What we want to see is the difference between 800 x 600 and 1280 x 720 windows. So when changing size, we specify Windowed with Set Fullscreen Mode . Do not expect a smaller frame while staying in Windowed Fullscreen.

The difference between Windowed, where the frame resizes, and Windowed Fullscreen, using the whole desktop

Quality can change several settings at once

Scalability adjusts quality such as shadows and draw distance, balancing looks against processing cost. Set Overall Scalability Level switches several settings at once.

Changing the overall quality shifts shadows, textures, view distance, and post processing together
ValueLevelOur option
0LowLow
1MediumMedium
2HighHigh
3EpicEpic
4CinematicNot added here

Meanwhile, Get Overall Scalability Level can return -1 when settings were adjusted individually. That is not an error; it means "not every item is on the same level".

So we put "Do not change" first in the dropdown. Not choosing a quality leaves individual settings and Cinematic alone. That prevents changing quality wholesale while only meaning to save volume.

Sponsored

Hands-On 1: display the settings screen

Build the practice screen

Save a Third Person template level under the name L_SettingsPractice . So you can test both window sizes, work with a desktop of at least 1600 x 900 where the candidate windows fit. If they do not fit, shrink the size options below.

Create WBP_SettingsPractice with User Widget as its parent. Place a Canvas Panel in the Designer and arrange these elements under it.

Canvas Panel
└─ Size Box
   └─ Border
      └─ Vertical Box
         ├─ Text "Settings"
         ├─ Text "Window size"
         ├─ Combo Box (String) "ResolutionCombo"
         ├─ Text "Quality"
         ├─ Combo Box (String) "QualityCombo"
         ├─ Text "Music volume (move to preview)"
         ├─ Slider "VolumeSlider"
         ├─ Button "ApplyButton"
         │  └─ Text "Apply and save"
         ├─ Text "CurrentSettingsText"
         └─ Text "StatusText"

The Size Box's Canvas slot uses center Anchors, Alignment 0.5 / 0.5 , Position 0 / 0 , and Auto Size on. Turn on the Size Box's Width Override at 520 and leave Height Override off. The Border is white with Padding 24 .

Text is navy, with the heading at Font Size 28 and other Text at 18 . Each element in the Vertical Box fills horizontally with vertical Padding 4 . The Text inside ApplyButton is centered with Padding 10 . Turn on Auto Wrap Text on the last two Texts so long strings wrap. Leave their initial text empty.

Set ApplyButton's Style Normal Tint to blue with only the button's Text in white. Set both Combo Boxes to Font Size 18 with navy Foreground Color.

Turn Is Variable on for the two named Combo Boxes, the Slider, the Button, and the last two Texts. That lets you drag them into the graph to read values and rewrite displays.

Layering elements from the Canvas Panel into a Vertical Box, stacking labels and controls in a 520-wide menu

The diagram shows the display once the logic is finished. The last two Texts can be empty for now.

Register the options in this order

A Combo Box (String) picks one string from a list of candidates. Add them to Details' Default Options in this order. Set Selected Option to Do not change on both.

IndexResolutionComboQualityCombo
0Do not changeDo not change
1800 x 600Low
21280 x 720Medium
3High
4Epic

An Index is the candidate number, starting at 0. We use this ordering later to decide "index 2 means 800 x 600". Do not add the "—" entries in the left column.

Set VolumeSlider's Min Value to 0 , Max Value to 1 , and Value to 0.5 . Leave Is Enabled off initially and turn it on once the music is ready.

Show it at level start

In L_SettingsPractice's Level Blueprint, wire from Event BeginPlay in this order. Get Player Controller uses Player Index 0 .

OrderNodeConnection / setting
1Create WidgetClass = WBP_SettingsPractice, Owning Player = Get Player Controller's Return Value
2Add to ViewportTarget = Create Widget's Return Value
3Set Input Mode UI OnlyPlayer Controller = Get Player Controller, In Widget to Focus empty, Mouse Lock = Do Not Lock
4Set Show Mouse CursorTarget = Get Player Controller, value on

The white exec order follows the table. Split Get Player Controller's blue output to the three places named.

Creating the settings screen at level start and passing Return Value to Add to Viewport's Target

Displaying it alone does not make it operable. Change the input destination too.

Passing the same Player Controller to UI Only and Show Mouse Cursor so the settings screen accepts the mouse

This exercise operates the settings screen with the mouse, so the Input Mode is UI Only. It is the combination of switching not only display but the input destination to the UI and showing the cursor.

Set the "Play" method to Standalone Game and start. If the dropdowns open and the button is clickable, the screen is ready. Choosing options does not change display settings yet. Close the game window when you are done.

Hands-On 2: apply the display settings

From here we work in WBP_SettingsPractice's Graph.

Create a variable VideoSettings typed Game User Settings Object Reference with default None. A reference names the same settings object later.

From Event On Initialized, wire white exec through Get Game User Settings → Set VideoSettings . Pass Get Game User Settings' Return Value to Set VideoSettings' value. On Initialized is called once when this Widget's instance initializes. Our screen is created exactly once at level start.

Fetching Game User Settings from the initialization event and keeping the reference in VideoSettings

What the "to the next diagram" label leads to is displaying the current values and loading the volume. Build up to here first and connect them after building each piece.

Split the apply logic into three stages

Create an argument-less function ApplyPracticeVideo and connect a Sequence from its entry. Use Add pin to reach Then 2.

Sequence advances through Then 0, then Then 1, then Then 2. We use no waiting logic here, so the order is "size → quality → apply at the end".

Sequence's Then 0 setting size, Then 1 setting quality, and Then 2 continuing to apply and save

Then 0: change window size only when chosen

Get Get Selected Index from ResolutionCombo's Get. Pass that integer to Switch on Int 's Selection and wire Then 0's white line to the Switch. Provide outputs 0, 1, and 2.

Switch on Int continues to the exec output matching the number it receives. Here it splits size settings by dropdown index.

Switch outputWhat to connect
0 / DefaultNothing
1Set Screen Resolution with Make Int Point (X=800, Y=600) → Set Fullscreen Mode (Windowed)
2Set Screen Resolution with Make Int Point (X=1280, Y=720) → Set Fullscreen Mode (Windowed)

Place a Set Screen Resolution and a Set Fullscreen Mode on both the 1 and 2 sides. Target on both is VideoSettings. Creating them by dragging from Get VideoSettings makes the target hard to get wrong.

Even with nothing connected to 0, the Sequence continues to Then 1. Values like -1 when nothing is selected go to Default, continuing without changing size.

Passing ResolutionCombo's selected Index to Switch on Int and continuing to size settings only on 1 and 2

The right edge of the diagram explains where each output goes. You do not create a "do not change" node.

From the Switch's 1, gathering 800 and 600 with Make Int Point and passing it to Set Screen Resolution

Specify the window format along with the resolution.

Specifying Windowed on the same VideoSettings so the window frame resizes too

Then 1: set quality in bulk only when chosen

Get Get Selected Index from QualityCombo and pass it to In Range (Integer) with Min 1 , Max 4 , and both Inclusive Min / Max on. It checks "is the number within 1 to 4".

Checking whether the selected Index falls between 1 and 4 and passing the Boolean to a Branch

From Then 1, continue to a Branch with In Range's Boolean output into Condition. A Boolean is true or false, here meaning "inside the range or not".

  • True: call Set Overall Scalability Level with Target = VideoSettings and Value = the selected Index minus 1
  • False: do nothing
From Then 1 to a Branch, continuing only the in-range True into the quality setting

"Low" is Index 1, but the quality value passed to UE is 0. An integer subtraction resolves that off-by-one. "Do not change" is outside the range, so Set is never called.

Subtracting 1 from the selected Index for the quality value and passing VideoSettings to the bulk quality node's Target

Then 2: apply and save together

Call Apply Settings from Then 2 with Target VideoSettings and Check for Command Line Overrides off. That input decides whether launch-time command specifications take priority; the exercise uses what you chose on screen.

Now, whether you chose a size and quality or left both at "Do not change", you reach one Apply Settings at the end. Do not add Save Settings.

Wire it to the button and test small

Add On Clicked from ApplyButton in the Designer and call Apply Practice Video (Target = Self). Connect a Print String after it showing Video settings applied .

Compile, save, and start in Standalone. Alternate between 800 x 600 and 1280 x 720 and press "Apply and save". A changing window size means the chain from UI to display settings works.

Switch quality between "Low" and "High". Shadow changes depend on the scene, so do not judge by looks alone; prepare the display below too.

Show the current settings on screen

Create an argument-less function RefreshPracticeStatus . From Get VideoSettings, fetch Get Screen Resolution and Get Overall Scalability Level.

Split Get Screen Resolution's return value into X and Y with Break Int Point . Convert the quality integer into a display name as follows.

  1. Add integer 1 to Get Overall Scalability Level's value. Individual settings' -1 becomes 0 and Low's 0 becomes 1.
  2. Pass that to a Select node's Index. Use Add pin to reach six options and set the output type to Text.
  3. Enter Individual / Low / Medium / High / Epic / Cinematic from Option 0 onward.

Select returns one value corresponding to a number. Unlike a Switch, which routes execution, here it chooses the text to display.

Adding 1 to the quality value and choosing among six display names from Individual to Cinematic with Select

Enter Current: {W} x {H} / Quality {Q} into Format Text 's Format and pass X to W, Y to H, and Select's Return Value to Q. Format Text fills values into the braces.

Splitting the resolution into width and height and combining them with the quality name into the current-value sentence

From the function entry, call CurrentSettingsText's Set Text and pass Format Text's Result to In Text.

Passing the built display text to CurrentSettingsText's Set Text

Call RefreshPracticeStatus from two places.

  • After Set VideoSettings in Event On Initialized
  • After Apply Settings in ApplyPracticeVideo's Then 2
Then 2 applying and saving with Apply Settings, then updating the current-value display

The dropdowns returning to "Do not change" at launch does not mean settings were lost. The dropdowns above are what you are about to change and the Text below is the settings currently held.

Sponsored

Hands-On 3: change and save the music volume

With display settings working, add music. Here we change the volume of one music track playing on the settings screen, not a game-wide master volume.

1. Prepare looping music

Drag a WAV file into the Content Browser to import it as a Sound Wave. Right-click that asset, choose Create Cue, and name the resulting Sound Cue SC_SettingsPracticeBGM . A Sound Cue assembles which sound plays and how.

Open the Sound Cue and connect the Wave Player with your audio to Output. Turn Looping on in the Wave Player's Details. Confirm it repeats in the preview and save.

So it can return from volume 0, set the Sound Cue's Virtualization Mode to Play When Silent , which keeps playback running while silent. We later lower the slider to 0 and raise it again.

2. Build the container that saves the volume

Create a Blueprint SG_SettingsPracticeAudio with SaveGame as its parent class. Add a Float variable BGMVolume with default 0.5 , then compile and save.

Float handles decimals such as 0.5. We use it to vary volume finely between 0 and 1.

Add these two variables to WBP_SettingsPractice as well.

VariableTypeDefault
AudioPreferencesSG_SettingsPracticeAudio Object ReferenceNone
PreviewAudioAudio Component Object ReferenceNone

AudioPreferences is the container holding the saved value and PreviewAudio is the reference controlling the sound actually playing. The value you save and the sound you are playing are handled separately even at the same volume.

Standardize the save location name as SettingsPracticeAudio with User Index 0 . A Slot Name identifies saved data. A single character differing between saving and loading means looking for different data.

3. Prepare defaults first, then read back if saved

Create argument-less functions LoadPracticeAudio and StartPracticeAudio and compile once.

Build LoadPracticeAudio in this order.

  1. Set Create Save Game Object 's Save Game Class to SG_SettingsPracticeAudio.
  2. Pass Return Value to Set AudioPreferences' value. Also wire white exec from Create to Set.
  3. Then call Does Save Game Exist with Slot Name SettingsPracticeAudio and User Index 0.
  4. Wire its exec output to a Branch and its Return Value to Condition.
Creating a SaveGame object holding the defaults and keeping it in AudioPreferences

On the Branch's False, call StartPracticeAudio (Target = Self) directly. With no saved data on the first run, we use the default 0.5 we just created.

Continuing to loading if saved data exists, or straight to playback with the default if not

On True, call Load Game from Slot with the same Slot Name and User Index. Pass its Return Value to Cast To SG_SettingsPracticeAudio 's Object and wire white exec into the Cast.

The Cast checks whether the loaded data can be treated as our SG_SettingsPracticeAudio. On success you can read its BGMVolume.

On a successful Cast, pass As SG Settings Practice Audio to Set AudioPreferences and then call StartPracticeAudio. That replaces the default container with the saved one.

On Cast Failed, Print String Audio preferences could not be loaded and then call StartPracticeAudio. Even when the read fails, the screen works with the initial 0.5.

Checking the loaded data with a Cast and replacing AudioPreferences on success, while failure still continues to playback with defaults

4. Start playback at the loaded volume

Inside StartPracticeAudio, get Get BGMVolume from Get AudioPreferences and pass it to Clamp (Float) with Min 0 and Max 1. Clamp keeps a value in range, matching the slider's range here.

Reading the volume saved in AudioPreferences and clamping it between 0 and 1

Wire white exec in this order.

OrderNodeConnection / setting
1VolumeSlider's Set ValueIn Value = Clamp's Return Value
2Spawn Sound 2DSound = SC_SettingsPracticeBGM, Volume Multiplier = the same Clamp Return Value, Pitch 1, Start Time 0, Persist Across Level Transition off, Auto Destroy on
3Set PreviewAudioValue = Spawn Sound 2D's Return Value
4VolumeSlider's Set Is EnabledIn Is Enabled = on

Spawn Sound 2D starts the sound and returns an Audio Component for controlling it. Passing the saved volume from the start avoids a burst of loud audio right after launch. Spawn Sound 2D official reference

Passing the same Clamp value to the slider and Spawn Sound 2D's volume, starting playback at the loaded volume

Keep the sound you started so you can change its volume later.

Keeping the playing Audio Component in PreviewAudio and enabling the VolumeSlider

Finally, connect LoadPracticeAudio after RefreshPracticeStatus in Event On Initialized. The launch order is "fetch and display display settings → load the volume → play music".

After Set VideoSettings, displaying the current values and calling the volume load, in the second half of startup

5. Move the slider and compare

Add VolumeSlider's On Value Changed. Wire the event's white exec output to the exec-pin Is Valid with Get PreviewAudio as Input Object.

From the Is Valid side, call Set Volume Multiplier with PreviewAudio as Target and On Value Changed's Value as New Volume Multiplier. Do nothing on Is Not Valid. That avoids operating on a nonexistent Audio Component if the value changes during initialization before playback starts.

On slider change, checking PreviewAudio exists and passing the new volume to that sound

Start in Standalone and move the slider. 1 is the original volume multiplier and 0.5 is half of it. That does not mean the perceived loudness is exactly half.

There is no save logic yet, so relaunching returns to the default. Next we keep the chosen volume too.

6. Save the volume from the same button

Create an argument-less function SavePracticeAudio .

From Get AudioPreferences' blue output create Set BGMVolume , passing VolumeSlider's Get Value as the value. The Set's Target is AudioPreferences. You do not create a same-named variable on the Widget.

Writing the slider's current value into AudioPreferences' BGMVolume

Connect Save Game to Slot after it with Save Game Object AudioPreferences, Slot Name SettingsPracticeAudio, and User Index 0. Wire its exec output to a Branch and its Return Value to Condition.

Saving AudioPreferences to the specified slot and branching on the Return Value
BranchWhat to do
TrueSet StatusText to "Applied display settings. Music volume saved."
FalseSet StatusText to "Display settings applied. Saving music volume failed."

That Return Value tells you whether the volume SaveGame saved. It is not a value judging Apply Settings' overall save success.

Showing a success or failure message in StatusText based on the save result

Make ApplyButton's On Clicked run Apply Practice Video → Save Practice Audio . Remove the earlier Print String. Display settings save via Apply Settings and volume via Save Game to Slot.

Calling display application and music volume saving in order from the Apply and save button

Relaunch and confirm

Compile, save, and launch Standalone Game. Our saved data is meant to persist into the next session, so verify accordingly.

ActionExpected result
Set size to 1280 x 720 and quality to High, then applyThe window resizes and the current display reads 1280 x 720 and High
Lower the volume a little and press Apply and saveThe music gets quieter and the volume save result appears
Lower the volume to 0 and raise it againSound returns from silence. If it does not, check the Sound Cue's Play When Silent
Close the game window and run the same exercise againThe launch settings persist and the music starts at the saved volume
Set size and quality to "Do not change" and save only volumeDisplay settings are not changed wholesale while volume updates
Change the volume to preview it and close without savingThe next launch returns to the last saved volume

The point is watching the applied result and the next launch, not just how the settings fields look . After confirming in Standalone, verify the same round trip in a packaged build. Editor launch settings and command-line specifications can affect window size too.

Applying, closing, and relaunching to confirm resolution, quality, and volume persist

When it does not work

SymptomWhere to check
The settings screen is visible but not clickableUI Only, Show Mouse Cursor, and elements' Is Enabled
The size does not changeWhether you run Standalone, whether you set Windowed, whether Then 2 reaches Apply Settings
The quality level is off by oneWhether you subtract 1 from the Combo's Index
Changing only volume also changes qualityWhether Set Overall Scalability Level is called only for Index 1 to 4
No musicThe Sound Cue preview alone, Spawn Sound 2D's Sound, the saved volume, whether Load continues to StartPracticeAudio
Moving the slider does not change the soundWhether Set Volume Multiplier's Target is PreviewAudio and whether Value is connected
The volume does not persistSet BGMVolume's Target, Save Game Object, and the Slot Name and User Index on save and load
The dropdown reads "Do not change" and settings look lostCheck current values in CurrentSettingsText. The dropdowns choose what to change next

Bonus: building it into your own game

Adding more resolution options. Our fixed two options are for practicing window sizes. In a product, prepare options matching your target environments and display modes. Get Supported Fullscreen Resolutions is a starting point for fullscreen and Get Convenient Windowed Resolutions for windowed. Also handle empty candidate arrays, a current value not among the candidates, and an unselected Index of -1.

A confirmation screen for reverting. If you also offer Fullscreen, asking "keep these settings?" and reverting on a timeout makes it easier to recover control. Apply Settings also saves, so design the revert path to apply and save the previous values too.

Volume beyond music. We control one PreviewAudio here. To adjust several music tracks and sound effects together, group sounds with Sound Classes and control them with Sound Mix or Audio Modulation. The idea of separating the saved value from applying it to actual sound stays the same.

Extending to an in-game settings menu. We create the Widget once at level start. To turn it into an openable menu, move music playback outside the screen so the same track does not stack each time you open it. For restoring input and cursor on close, the pause menu article is the continuation.

The scale of your save logic. Our SaveGame holds one volume value, so we used the normal blocking save and load. If you handle large progress data at the same time, consider asynchronous saving. See Epic's saving and loading your game for details.

Summary

Display settings pass values into Game User Settings and Apply Settings applies and saves them. Music volume applies to the playing Audio Component, and the value kept in a SaveGame is read back on the next launch.

Start by changing the window size and music volume and closing the game. If it comes back the way you chose, you have moved from "UI you can merely pick things in" to a settings screen that actually tunes playability.

Reference: Overall scalability values, Quality value with individual settings, Sound Cue and looping, Save Game to Slot

To extend the settings screen to multiple languages, move on to switching languages with the Localization Dashboard.

Unreal Engine Notes in this section98