[go: up one dir, main page]

Steamworks Documentation
Unreal Engine
Developing in Unreal Engine for Steam Frame provides several options for deployment. If you already have a well-optimized PCVR build, you may want to see if adjusting quality settings is sufficient for making framerate. We currently recommend targeting Android to take full advantage of optimizations tailored for mobile hardware.

First, make sure you have turned on Developer Mode as described in the Setting up your Steam Frame for development this will let you deploy to the headset.

Steam Frame has a custom plugin to take advantage of some of the features of the hardware, and there are some changes to the engine that are recommended to run as smoothly as possible. We have created a changelist in our GitHub repo that can be cherry-picked into your Unreal Engine build to take full advantage of the hardware and its features.

If you are already set up to build Unreal Engine, cherry pick the following commit:
https://github.com/Valve-VR/UnrealEngine/commit/751cf4a5135bb0ac0167260e7012b974085534b2
If you get a 404 for the above URL, you need to accept Epic's EULA as described here.

If you are using Git on the command line, you can cherry pick it using the following command:
git remote add valve git@github.com:Valve-VR/UnrealEngine.git git fetch valve 751cf4a5135bb0ac0167260e7012b974085534b2 git cherry-pick 751cf4a5135bb0ac0167260e7012b974085534b2

Or by using your Git GUI client of choice.

If you have not set up Unreal to build before, please see Epic's Getting Started guide for more information. You will also need to install the Android NDK and SDK. More information from Epic on how to set this up for your version of Unreal can be found in this guide.

Android Project Settings

For the best results and optimizations out of the gate, we recommend starting with the VRTemplate project as your base.

Since the VR Template already targets Android out of the box, it can run directly with no changes.  However, to get the best performance, we want to make a few modifications.

  • In Project Settings > Platforms - Android, check Support Vulkan, and ensure that Detect Vulkan device support is also checked.
  • In the same section, ensure that Package for Valve Steam Frame devices is checked, and Package for Meta Quest devices is unchecked.
  • For consistency during development, you may also want to change the default Windows API to Vulkan as well.
  • Change the default anti-aliasing method for mobile to MSAA in Project Settings > Engine - Rendering, and set MSAA sample count (Default Settings) to 4x MSAA.
  • Under the Edit > Plugins menu, locate the Steam Frame OpenXR Extension in the list, and enable it.
  • (Optional, but recommended)  Disable the Android File Server, which will speed up deployment and development times

Depending on the needs of your project, other features can be disabled to save rendering performance, such as disabling Custom Depth if not needed.  For more information, see the following documentation page:  XR Best Practices in Unreal

Due to a bug in the current versions of Unreal Engine, you must also use the Binned2 allocator to prevent a crash on startup. This should be fixed in future versions of the engine, but in the meantime, open up your new project's Target.cs file, and add the following line:

StaticAllocator = StaticAllocatorType.Binned2;

Finally, you must make sure that the application uses the proper version of the Android SDK and NDK for the device (currently, 30). In your project's settings, go to Edit > Project Settings > Android SDK, and set both the Android SDK and the Android NDK API Levelto android-30. Alternatively, you can edit your project's config DefaultEngine.ini to have the following:
[/script/androidruntimesettings.androidruntimesettings] MinSDKVersion=30 TargetSDKVersion=30 SDKAPILevelOverride=30 NDKAPILevelOverride=android-30 BuildToolsOverride=30.0.0

Deploying and Running on Steam Frame

Before we can deploy the Project, we need to make sure that the device is connected through the Android Debug Bridge (ADB). This is a standard Android workflow, so it should be familiar to anyone that has worked on other Android-based platforms.

Refer to this article to get started: Connecting adb to Lepton

Once your project is set up, you should be able to package it for Android as you would any other project. The simplest way is to go to the Platforms drop down in the Editor, and under Quick Launch > Android at the top, you should see a device labeled Lepton. Simply click that and deploy to the device!

In the Editor, under the Platforms drop down, ensure that the Android flavor is set to Android (ASTC), and then select Package Project.
Your options when packaging are ASTC, ECT2, or Default. Any will work but ASTC is best supported on the chipset.

Once your package is deployed and running, the Device Output window in the editor will show you the live output logs from the game, as well as allow you to access console commands to send to the game. This is very useful for debugging and tuning!

Steam Frame Controllers

While SteamVR will automatically remap bindings from other controllers if no bindings are provided for the Frame Controllers, specifying native bindings will always give the best user experience. To add bindings for Steam Frame Controllers you must have the SteamFrameOpenXRExtension plugin enabled. Then related Input Keys will show up in Unreal Engine's keybinding system.
In the section marked Input Mapping Contexts (IMC) the Steam Frame controller keys will appear as options.  Ensure that the Input Action types match the type of key input that you bind them to!

Variable Rate Shading (VRS)

The Steam Frame Unreal Engine plugin supports Variable Rate Shading (VRS), which allows the engine to manage the resolution at which different areas of the screen are rendered.  This allows for foveated rendering, where the user’s gaze location is rendered at full resolution, while areas of the screen that are farther away are rendered at a lower resolution in order to save GPU time.
There are two variants of VRS for Steam Frame devices: runtime-provided VRS, which allows the runtime to provide the application with a foveation map to use, and the Legacy VRS system, which allows for application-driven setting of the Fragment Density Map (FDM).  Both variants are eye-tracked.
We recommend using the Runtime-Provided VRS implementation, unless you want to experiment with performance by fine tuning the foveation map yourself.

Both types of VRS requires multi-view, so be sure to check the following settings in your project:
vr.MobileMultiView=True

Enabling Runtime-Provided VRS (recommended)

This will let the runtime scale up and down the amount of foveation depending on your application’s GPU performance.
To enable this feature in your project, open up the project’s DefaultEngine.ini, and add the following settings to the /Script/Engine.RendererSettings section:
[/script/engine.renderersettings] r.Vulkan.VRSFormat=5
If you’re on Unreal Engine 5.5 or above, you also need to add
r.VRS.Support=1 r.VRS.Enable=1 xr.OpenXRFBFoveationLevel=3

In your project’s DefaultGame.ini, add the following to enable the required OpenXR extension:
[/script/openxrhmd.openxrhmdsettings] bIsFBFoveationEnabled=true

Legacy VRS

To enable this feature in your project, open up the project’s DefaultEngine.ini, and add the following settings to the /Script/Engine.RendererSettings section:

[/script/engine.renderersettings] xr.VRS.FoveationLevel=0 r.Vulkan.VRSFormat=5 xr.VRS.SteamFrame.FoveationLevel=3 ; Any number 0 - 3 is valid

If you’re on Unreal Engine 5.5 or above, you also need to add

r.VRS.Support=1 r.VRS.Enable=1

You'll need to turn off the default Unreal Engine VRS, which is not compatible with multi-view VR rendering. Having both enabled will result in a black screen. In your project’s DefaultGame.ini, add the following to disable the built-in runtime-provided VRS provider:

[/script/openxrhmd.openxrhmdsettings] bIsFBFoveationEnabled=false

There are a few other CVars that can be modified in settings or runtime order to tweak the performance and characteristics of foveated rendering:

  • xr.VRS.SteamFrame.FoveationLevel - When greater than 0, foveation will be enabled.  The max level, 3, represents the highest overall image quality, with the worst performance.  The minimum active level, 0, represents the lowest overall image quality, but the maximum performance.  -1 (default) disables foveation.

  • xr.VRS.SteamFrame.DynamicFoveation - When set to 1, the foveation amount will change based on current measured GPU load to try and maintain the target framerate.  Currently unimplemented

  • xr.VRS.SteamFrame.ForceDynamicFoveationBucket - Used at runtime to force the Dynamic Foveation to use settings from a specified bucket for testing purposes.

Note that currently because of the binning size, it can be hard to see the effect of gaze tracked foveation.

Runtime Foveation Testing Variables (Legacy only)


  • xr.VRS.SteamFrame.EnableTestFoveation - When set to 1, foveation parameters will lock to the values set below.  This is useful for testing at runtime to check the visual effect on the game of different parameter values for the dynamic foveation buckets.

  • xr.VRS.SteamFrame.TestFoveation.FovealDensity - The density, in the range from (0.0, 1.0] for the center foveal region of the screen.  This is a pixel divisor, so sampling will occur at 1.0 / Density.  Because of this, note that the lower the value of the density, the bigger the effect on quality!

  • xr.VRS.SteamFrame.TestFoveation.FovealWidth - The size, in float percentage of the screen diagonal (0.0, 1.0], for the foveal region of the screen where FovealDensity is applied.

  • xr.VRS.SteamFrame.TestFoveation.MidBandDensity - The same as FovealDensity, but for the mid-quality band immediately outside the foveal region.

  • xr.VRS.SteamFrame.TestFoveation.MidBandWidth - The size, in float percentage of the screen diagonal (0.0, 1.0], for the mid-quality band immediately outside of the foveal region.  Should be larger than FovealWidth.

  • xr.VRS.SteamFrame.TestFoveation.PeripheralDensity - The same as FovealDensity, but for pixels outside of the mid-quality band.

Important Note:  The density value is read from the density map once per bin.  This means that the foveation values may appear to affect much larger regions of the screen than would be expected and may appear blocky.  You may need to adjust your settings to compensate!

Adding Steamworks Support for Android

Support for running applications with Steamworks support enabled is available.  To enable it, ensure that the plugin is enabled by going to Window > Plugins in the Editor and making sure Online Subsystem Steam is enabled.
With that enabled, update your application’s DefaultEngine.ini file with the following, being sure to replace the SteamDevAppId with your own AppId:
[/script/engine.gameengine] +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver") [OnlineSubsystem] DefaultPlatformService=Steam [OnlineSubsystemSteam] bEnabled=true SteamDevAppId=12345 ; If using Sessions bInitServerOnClient=true [/script/onlinesubsystemsteam.steamnetdriver] NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection" [/script/androidruntimesettings.androidruntimesettings] bDisableLibCppSharedDependencyValidation=True bSkipLibCpp=false

Debugging and Profiling

Please see the main Steam Frame Debugging page for general information on the options available for debugging games on Steam Frame.

Unreal Insights

Unreal Insights is Unreal Engine’s own profiling tool, which can do both CPU and GPU captures. For more documentation on the use of the tool, see https://docs.unrealengine.com/4.26/en-US/TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/

To use Unreal Insights within Lepton, you must manually set up a commandline to point at the tracehost on your PC, as well as set up port forwarding. On the host PC, after connecting adb to Lepton, do the following:
adb shell setprop debug.ue.commandline -tracehost=127.0.0.1 exit adb reverse tcp:1981 tcp:1981

Finally, launch Unreal Insights located under your depot at Engine/Binaries/Win64/UnrealInsights.exe (you may have to build it first). You should see the device appear under Session. Attach, and profile as per the documentation above.

Native LinuxArm64 Support

In addition to running through Lepton with Unreal Engine's Android support, your project can also directly run on SteamOS using Unreal Engine's LinuxArm64 platform support. While most of the workflows and behavior are the same between the two, there are some differences highlighted below.

Code Requirements

In order to use LinuxArm64 on the device, there is an additional commit that needs to be pulled from GitHub. This code adds support for detecting the device on startup and setting scalability, adds support for additional texture formats on LinuxArm64, as well as provide a few feature fixes to Unreal Engine that should be rolled into future Engine updates.

If you are using Git on the commandline, and assuming you already cherry picked the Android support changelist from the first section of this document, cherry pick the additional change:
git fetch valve d4e9e50790e1197565ef8486eb33bdfc2490b37f git cherry-pick d4e9e50790e1197565ef8486eb33bdfc2490b37f

Or by using the Git GUI client of choice.

Additionally, you will need the Linux cross compilation toolchain installed. Please see this guide from Epic on how to set it up: https://dev.epicgames.com/documentation/en-us/unreal-engine/linux-development-requirements-for-unreal-engine

Project Setup Requirements

Projects need to be configured to tell Unreal Engine that they want to support the LinuxArm64 platform. To do this, open your project's .uproject file (located in your project's root directory), and make sure that LinuxArm64 is listed under both the TargetPlatforms section and the OpenXR Plugin's SupportedTargetPlatforms section, as in the example below:
{ "FileVersion": 3, "EngineAssociation": "", "Category": "", "Description": "", "Plugins": [ { "Name": "OpenXR", "Enabled": true, "SupportedTargetPlatforms": [ "Win64", "Linux", "LinuxArm64", "Android", "HoloLens" ] } ], "TargetPlatforms": [ "Android", "IOS", "Linux", "LinuxArm64", "Mac", "PS4", "PS5", "Windows", "WindowsNoEditor", "Switch", "XboxOne", "XSX", "HoloLens" ] }

Once the LinuxArm64 platform has been added, build the project, and launch the editor. LinuxArm64 should now appear as a platform choice under the Platforms button.

Project Settings

In addition to the project settings in the previous section of the documentation, it is also recommended that you change the Targeted RHI setting in your Project Settings under Platforms - Linux to Vulkan Mobile (ES3.1) and disable Vulkan Desktop (SM5).

Packaging and Deploying to Steam Frame

Under the Platforms drop down at the top of the Editor window, you should see LinuxArm64 as an option. Within that section, you'll also see an additional option for Flavor Selection. For best performance, we recommend LinuxArm64 (ASTC). Click Package Project to initiate a Build.

Once built, follow the instructions to deploy the packaged project to the device using the DevKit Tool.

Common Problems

Android application crashes shortly after launch, with a stack that involves UnrealMemory.cpp

This is due to the default allocator becoming Binned3 for Android apps in recent versions of Unreal.  Binned3 allocates a large chunk of memory at the beginning of the app load, which is unfortunately too large, and causes an out of memory (OOM) crash.
To fix this, restore the Binned2 allocator in your project’s Target.cs file with the following line:
StaticAllocator = StaticAllocatorType.Binned2;

Can’t Install APK on Lepton because of SDK Error

If you see an error like the following when installing the APK on Lepton, it indicates that the Project is built with a version of the Android SDK / NDK that is too new for the version of Android on the device.
Failure [INSTALL_FAILED_OLDER_SDK: Failed parse during installPackageLI: /data/app/vmdl157345552.tmp/base.apk (at Binary XML file line #8): Requires newer sdk version #33 (current version is #30)]

Note:  This message is very confusing!  It indicates that the APK requires a newer SDK than the OS supports, and not the other way around.

To fix this, you must manually specify the project uses a lower SDK/NDK level, and rebuild.  In your Project’s settings.  Go to Edit > Project Settings > Android SDK > NDK API Level and set it to android-30  (or, in the future, whichever version is specified after the (current version is #XX) portion of the error).  Repackage and install, and the APK should install without error.

Alternatively, you can change the projects DefaultEngine.ini file to have the following:
[/script/androidruntimesettings.androidruntimesettings] MinSDKVersion=30 TargetSDKVersion=30 SDKAPILevelOverride=30 NDKAPILevelOverride=android-30 BuildToolsOverride=30.0.0