Setting up Scalability and Device Profiles For A Project
Unreal Engine provides a wide variety of Scalability settings that can affect your project's performance and visual quality. Usually, the engine default settings will accommodate most of your needs, however, you may want to change these settings for better performance or higher quality. Projects can launch on multiple platforms, therefore the Scalability settings may require different values for different platforms. The behavior of Platforms such as the PC is open to encompass a wide range of different types of hardware, as a result, these settings may need to be adjusted by individual users to best match their particular system.
Scalability and Device Settings Systems
To achieve your goals in Scalability, multiple engine systems can be used together to create project profile configurations that work across all platforms and users. Below, you will find an explanation of the different engine systems involved in this process.
Console Variables
Most performance and quality settings are implemented in the engine as Console Variables (CVars). These are named variables that store numbers, strings, or enumeration values. Console variables have a default set in source code, which can then be overridden by game-specific config files or the other systems described below. Most variables can be set while the game is running or from the command line, which provides a preview of quality and performance settings before committing them to a value. You can add data-driven CVars to your project by clicking on the Toolbar and navigating to Edit > Engine >Data Driven Cvar > CVars Array and clicking on the Add(+) button.
Pictured above are the Data Driven CVars Array located in the Project Settings.
Device Profiles
The engine uses Device Profiles to define a hierarchy for different types of physical devices that may run your project. You can find these settings by navigating to the Toolbar and clicking on Tools >Instrumentation > Platforms > Device Profiles.
As an example, in the default engine settings there is a base "Android" device profile that is used for every Android device.
In the Device Profiles settings you can access Existing Device Profiles(1), additionally, you can edit your own Console Variables in the CVars column(2).
Below the base profile are multiple performance buckets such as "Android_High", and specific CPU/GPU types below that profile. When the project is launched the engine uses a customizable process to determine which specific device profile to use, then applies the settings associated with that profile, starting from the top level such as "Android" and overriding it with any values set in the more specific profiles below it.
Scalability Groups
The scalability system is used to define a related set of performance settings that can be selected at runtime. For example, the engine default PostProcessQuality group defines settings for Motion Blur and Bloom and is split into 4 levels ranging from Low to Epic as well as a Cinematic level for maximum quality. When the project or user chooses a specific scalability group quality level, it will apply all of the console variables in that quality level.
Scalability groups apply their console variable settings before device profiles. Settings defined in specific device profiles will override those in scalability groups chosen by the user. This means that device profiles can specify a base scalability group console variable like sg.PostProcessQuality
before overriding individual settings.
It is possible to create platform-specific scalability group settings by using the general platform config override system described below. However, it is not possible to set up different scalability groups for specific device profiles.
In general, scalability groups are useful on open platforms like PC because they allow users to take advantage of a varying range of PC hardware components.
Game User Settings
The UGameUserSettings
class stores all settings that an individual user can change from an options UI menu. The user's specified settings are stored in a GameUserSettings.ini file on the specific device that runs your project. On some platforms that restrict file access, platform-specific options need to be enabled to allow the game user settings to save and load properly. The default engine class stores the user's choice of quality for each scalability group in addition to specific settings such as window resolution.
Many projects may want to use a game-specific subclass, which is done by creating a native subclass and then modifying the GameUserSettings Class Name. This can be done from the DefaultEngine.ini
file, by navigating to the [/Script/Engine.Engine] section, or by navigating to Edit > Project Settings > Engine > General Settings > Default Classes > Advanced > Game User Settings Class.
In your game-specific settings class, you can add new settings or change how settings are applied at runtime. Default values for a specific game can be set in the game's DefaultGameUserSettings.ini
file, which will be used for any new users. The Game User Settings are exposed to Blueprint and have useful functions that can be called from either a Blueprint-based settings UI or in source code.
For example, the RunHardwareBenchmark
function runs an automated benchmark that detects the relative CPU and GPU speed of the local machine and uses the Scalability.ini
settings starting with PerfIndexThresholds
to estimate the best scalability group settings for a particular machine. ApplyHardwareBenchmarkResults
can then be called to apply and save the settings.
Texture Group Settings
When textures are created in the editor, they can be assigned to different groups such as "World" or "UI". These groups specify what Texture Settings are applied at runtime. Each group has different settings for maximum size, mip levels, and texture group settings that can be customized for specific device profiles. Packaging takes these settings into account. You can set a lower maximum resolution for mobile builds and the install package will only include the mip levels that could be streamed on that device. Texture group settings do not use console variables directly because they cannot be modified at runtime.
Setting Priority
Before settings are applied, they are loaded from config files. The core Configuration File Hierarchy is used to determine what settings will be applied. This priority matters for any settings loaded from config files that cannot be modified at runtime. For settings that use the Console Variable system and can be modified at runtime, they are applied in the following order with higher numbers overriding lower numbers. This order is defined in the EConsoleVariableFlags
enum:
Priority Order |
Flag |
Description |
||
---|---|---|---|---|
1 |
SetByConstructor |
The default value set in a console variable's constructor. |
||
2 |
SetByScalability |
Values set by scalability group quality levels. |
||
3 |
SetByGameSetting |
Low priority values set by the engine's GameUserSettings. |
||
4 |
SetByProjectSetting |
Sets the ProjectSettings from the DefaultEngine.ini file from sections such as [/Script/Engine.RendererSettings]. These settings are usually set by the Project Settings menu located in the editor. |
||
5 |
SetBySystemSettingsIni |
The [ConsoleVariables] and [SystemSettings] sections of |
||
6 |
SetByDeviceProfile |
From device profiles, with the more specific profiles overriding generic ones. |
||
7 |
SetByGameOverride |
High priority values set by a game's GameUserSettings subclass, this should be used for settings that need to override device profiles. |
||
8 |
SetByConsoleVariablesIni |
The engine |
||
9 |
SetByCommandline |
Used by some command line options. |
||
10 |
SetByCode |
Used by various debugging tools. |
||
11 |
SetByConsole |
The highest priority, set by typing "NameOfCVar Value" in the console of a running game |
As an example the engine override process is demonstrated in this diagram that begins with the Scalability Group system. First, the engine checks the [PostProcessing@2] category (displayed as High in the UI) in the engine-provided BaseScalability.ini
file which contains the Console Variables(CVar) for bloom.
Then, the engine will check to see if any of these settings have been overridden by the category [PostProcessing@2] in the game-specific DefaultScalability.ini
file or platform-specific files like WindowsScalability.ini
.
Next, the Engine checks CVars specified in the [SystemSettings] category beginning with the BaseEngine.ini file
. Any overrides in DefaultEngine.ini
or a platform-specific ini are applied as before.
The call order continues down into the Device Profiles system. First, the Device Profile Matching Rules are run to determine the lowest level device profile that should be applied (Android Galaxy in this case).
Next, it starts applying rules by first applying the highest level device profile (Android) that matches the device. It starts by checking the CVars in the engine-provided BaseDeviceProfiles.ini
, then checks the game-specific DefaultDeviceProfiles.ini
to see if any of the CVars have been overridden.
This process continues down the hierarchy and checks the AndroidMid and the Android Galaxy device profile settings in a similar process to the Android call described above. Once all device profiles have been applied, it would continue on to apply any overrides at higher priority levels described above.
Setting Game-Specific Overrides
If you want to change a specific setting for your game, then you need to set up the configuration files. The settings are stored in several different locations, so this is a multi-step process that begins with finding the correct setting.
In the examples below, we will demonstrate the process of starting with a general concept such as "bloom quality" to finding a specific setting like r.BloomQuality
. You can find this setting from either an .ini
file, the in-editor Console Variable list, or in the source code.
Engine Configuration: BaseScalability.ini
Begin by navigating to your Engine/Config
folder, and clicking on the BaseScalability.ini
file. Once you have opened the file, you can look for the PostProcessQuality group section to find the variable r.BloomQuality
.
[PostProcessQuality@0]
r.MotionBlurQuality=0
r.MotionBlur.HalfResGather=1
r.AmbientOcclusionMipLevelFactor=1.0
r.AmbientOcclusionMaxQuality=0
r.AmbientOcclusionLevels=0
r.AmbientOcclusionRadiusScale=1.2
r.DepthOfFieldQuality=0
r.RenderTargetPoolMin=300
r.LensFlareQuality=0
r.SceneColorFringeQuality=0
r.EyeAdaptationQuality=2
r.BloomQuality=4
Device Profiles: Console Variables
Open the Device Profile editor by navigating to Tools->Platforms->Device Profiles. Once in the editor, locate the Windows profile, then in the CVars column, click the Edit icon next to Windows.
This opens a window with a categorized list of all Console Variables that can be set from Device Profiles:
The Bloom Quality variable pictured in the image above is listed in the Rendering category.
Editor Command Line
Open up a running game or editor window, hit the tilde key(~) to open the full console, then in the Cmd line text field, type in "Bloom". The autocomplete section will list all console variables that include "Bloom" and can be set at runtime, which includes r.BloomQuality
.
Manually Searching
You can search all .ini
files in the engine for a term like "bloom" using a code editor such as Visual Studio that supports a text search within the engine directories. Alternatively, you can search the Engine API code base for specific terms. Once you find your specified console variable or config setting, we recommend you search all engine .ini
files for that setting so you know where it is set, then you can apply your game or platform-specific setting.
Overriding Settings In Config Files
If you want a Console Variable setting to always be the same across all platforms and scalability groups, this can be done from the [ConsoleVariables] section of the DefaultEngine.ini
file. As an example, we can override bloom quality in all cases by adding the following to the DefaultEngine.ini
file.
[ConsoleVariables]
r.BloomQuality=1
If the setting you are seeking is in the BaseScalability.ini
or another config file, then you can override it by creating a new config file in your project. To do this, create or edit the file in your project's config directory that matches the same name as the engine, but instead use the Base to replace the Default. You can add or find a section with the same name as the variable in the Engine. For instance, to change the bloom quality for the Low quality post process scalability group, you can add this text to the DefaultScalability.ini
file.
[PostProcessQuality@0]
r.BloomQuality=1
If the engine sets a Console Variable in a platform-specific config file such as WindowsEngine.ini, then you can override this setting for a specific platform using the same platform-specific config files. Additionally, you can change any platform-specific settings that do not use the device profile or console variable system. To do this, make a new platform-specific config file that matches the same config in the engine. For example, to override the Engine/Config/Windows/WindowsEngine.ini
file, You can make a new ProjectName/Config/Windows/WindowsEngine.ini
file, and make the same type of changes described above.
For platforms such as consoles that use the top level Platforms directory in the engine, we recommend that you make a parallel directory in your project folder. You can create a PlatformNameScalability.ini
file in the correct directory, and this will provide you with the ability to override scalability groups for specific platforms such as Android.
Setting Up Device Profiles
To accomodate device-specific differences, you will need to set up your project-specific device profile hierarchies. The easiest way to do this is using the Device Profile editor found by navigating to Tools > Platforms > Device Profiles. Once you are in the editor, click the Edit icon next to the device profile you want to set values for:
We recommend that you edit the highest-level profile that includes all devices you want to change. Then, edit the console variables list to add or remove settings for the profile you want to change:
This screen will not save your changes. Unlike other settings screens in the editor you will need to open the DefaultDeviceProfiles.ini
file using the button at the top of the editor, then when you are finished editing, click Save as Defaults to write the changes out to your project's DefaultDeviceProfiles.ini
file. If your editor is connected to source control you may need to click that same area to check out or add that file to source control. This editor save will only write the modified profiles, but you may want to manually fix the resulting .ini file to make it easier to read.
Texture LODGroups settings for specific platforms can be set from the Device Profiles window, by clicking the Edit icon in the TextureLODGroups column.
If you have a lot of platforms that will run your project, then it may be easier to choose to override the engine defaults by adding a [/Script/Engine.TextureLODSettings] section to your DefaultDeviceProfiles.ini
. You can also add additional device profiles by adding new DeviceProfileNameAndTypes
entries to the [DeviceProfiles] section. Following these methods, your settings will now be working as you intend. However, because of the setting priority hierarchy described in the table above, the engine settings at a higher priority may conflict with Project-specific settings at a lower priority.
For example, if the engine sets a variable in the DefaultDeviceProfiles.ini
, but you want to set it by scalability groups, then you will have to undo the engine's device profile setting.
Undoing an Existing Engine Setting
In some cases, you need to undo the engine's default value for a setting because it causes a conflict with your desired setting. Usually, this behavior is because you want to move a setting to a different level in the setting priority list, or move things between scalability groups. As an example, we want to move Bloom Quality from the PostProcess Scalability bucket to the Effects bucket. This can be done by opening your DefaultScalability.ini
file and adding lines similar to the examples below:
[PostProcessQuality@0]
-r.BloomQuality=4
[PostProcessQuality@1]
-r.BloomQuality=4
[PostProcessQuality@2]
-r.BloomQuality=5
[PostProcessQuality@3]
-r.BloomQuality=5
[PostProcessQuality@Cine]
-r.BloomQuality=5
[EffectsQuality@0]
r.BloomQuality=2
[EffectsQuality@1]
r.BloomQuality=2
[EffectsQuality@2]
r.BloomQuality=2
[EffectsQuality@3]
r.BloomQuality=5
[EffectsQuality@Cine]
r.BloomQuality=5
This uses an advanced configuration system syntax where you use a line starting with a ‘-' to cancel the engine change in one category (the line in the DefaultScalability needs to match the line in BaseScalability exactly other than the -), and then move it to a new category.
Overriding an Array such as the CVars array located in the BaseDeviceProfiles.ini
file, can be accomplished using two different methods. If you use the Device Profile window in the editor and save your settings, then it will create a DefaultDeviceProfile with multiple -CVars=
lines that will cancel each individual default element in the array.
If you want to wipe out an entire array set by the engine and replace it, you can use the line:
!Cvars=ClearArray
then add new elements by using the line:
+CVars
Additionally, if the base array uses the @Array=Key
syntax, then it is treated like a Map, and you can override lines using that key.
As an example, the lines below can be added to the DefaultDeviceProfiles.ini
file to set the World Normal Map textures to automatically reduce to a dimension of 2048x2048 (if they are larger than that amount).
The line @TextureLODGroups=Group
located in the BaseDeviceProfiles.ini
, means you do not need to remove the old value with a -
or a !
preface :
[/Script/Engine.TextureLODSettings]
+TextureLODGroups=(Group=TEXTUREGROUP_WorldNormalMap,MinLODSize=1,MaxLODSize=2048,LODBias=0,MinMagFilter=aniso,MipFilter=point,MipGenSettings=TMGS_SimpleAverage)
Lyra Examples
The Lyra game sample serves as an example for how to combine these different features for your specific project. In the sections below you will observe how the different components come together.
Scalability Groups
The Lyra/Config/DefaultScalability.ini
file was created manually, by copying and renaming the BaseScalability.ini
file located in the Engine/Config
folder, then editing it to remove any redundant sections.
The file has two sets of changes that tweak how the scalability groups work:
The Performance Thresholds used by the automated benchmark tools have now been raised from the original engine defaults, as a result faster computers are required to reach High or Epic quality levels.
The
foliage.DensityScale
andgrass.DensityScale
Console Variable settings have been moved out of the FoliageQuality category and into the ViewDistanceQuality category.
This is done to make a simplified options menu UI because it is unnecessary to single out foliage quality for a specific game.
Device Profiles
The DefaultDeviceProfiles.ini
file was created using the Save To Defaults option in the Device Profile window located in the editor, then these values were manually edited to add additional profiles, and modified later using the Device Profile window to tweak individual settings.
It includes the following changes:
A default texture group override was added to define settings for a game-specific "UI With MIPs" category, which is named in the editor using the [EnumRemap] section in
DefaultEngine.ini
.A new Mobile device profile was added to serve as a base profile for IOS and Android.
The new Mobile profile was defined with a new CVar setting and override texture groups to reduce the maximum Mip size on mobile devices to save on memory and download size. These sizes are applied at cooking time.
The IOS and Android device profiles were modified to set their base profile to the new Mobile profile.
Platform Configuration Files
Platform configuration files provide an example to create files for your own project. Config files for public platforms are available in the Default*.ini
file located in the Config folder. Supported platforms that require licensing from the platform holder, such as game consoles, are available in the Lyra/Config/PlatformName/PlatformName*.ini
directory.
If you have a license for a non-public platform, you can contact your Epic partner. See Epic Online Services for additional information.
Lyra includes a custom configuration option that can be used to create distribution-specific variants of a game. For example, if your game is shipping on multiple Windows-based stores, you can create subfolders inside the Config/Custom folder that contains the .ini files that override the store-specific settings.
These .ini
file overrides are enabled with the development command line option:
-CustomConfig=Directory
Alternatively, you can use the CustomConfig parameter located in a Target.cs
file. Platform-specific custom config files can be added by creating files named using a file path similar to Config/Custom/CustomConfigName/PlatformName/PlatformNameEngine.ini
.
Game User Settings
For handling user specific device settings, Lyra uses the ULyraSettingsLocal
class as a subclass of UGameUserSettings
. Lyra uses the same settings UI to modify the local settings such as Volume and Graphics Quality which are only stored on the device, and the ULyraSettingsShared
class to handle key bindings which can be written to cloud storage and used on multiple devices.
Refer to the GameSettings plugin documentation for further information.