Develop

Unity Performance Settings sample

Updated: May 11, 2026

Overview

This sample demonstrates runtime performance optimization controls available for Meta Quest applications built with Unity. It provides an interactive testing environment where you can adjust CPU/GPU performance levels, rendering features, and stress test parameters while observing immediate effects on frame rate and resource utilization.

What you will learn

  • Control CPU and GPU performance levels dynamically using OVRPlugin APIs
  • Implement Fixed Foveated Rendering (FFR) with static and dynamic modes
  • Adjust resolution scaling using the two-factor system combining eyeTextureResolutionScale and renderViewportScale
  • Configure dynamic resolution, MSAA, and Application SpaceWarp at runtime
  • Create stress tests using Unity’s Job System and dynamic mesh instantiation
  • Build compositor layer UI that remains unaffected by render scale changes

Requirements

  • Device: Quest 2, Quest 3, or Quest 3S
  • Development environment: Unity 6000.0.59f2 or newer with Android build support
For complete platform setup instructions, see the Meta Quest development documentation.

Get started

Clone the repository from Unity-PerformanceSettings and open the project in Unity 6. The editor window at Meta > Unity Performance Settings Sample Intro Window provides build-time configuration options. Open Assets/PerformanceSettings/Scenes/MainScene.unity and build to your Quest device. For detailed build instructions and dependency versions, see the README.

Explore the sample

The sample contains two interactive screens accessible via controller pointing and trigger press. Both screens are rendered as compositor layers for consistent clarity regardless of rendering settings.
File / SceneWhat it demonstratesKey concepts
MainScene.unity
Main environment with two interactive panels
Compositor layer UI, OVR SDK integration
RenderingAndPerf.cs
All runtime performance controls on the main panel
OVRPlugin APIs, URP pipeline access, dynamic UI generation
LogSection.cs
In-game debug console on the Logs panel
Thread-safe logging, Application.logMessageReceivedThreaded
PushCPUJob.cs
Multi-threaded CPU stress test
Unity Job System, IJobParallelFor with 10,000 parallel jobs
SetLabelValueTo.cs
Real-time rendering metrics display
Per-frame XR resolution queries
IntroEditorWindow.cs
Editor window for build-time settings
AndroidManifest.xml manipulation, dual-core mode configuration

Runtime behavior

The Performance, CPU & GPU Levels panel provides real-time controls for framerate targets, FFR modes, MSAA quality, resolution scaling, CPU/GPU performance levels, passthrough, and Application SpaceWarp.
Toggle buttons are generated dynamically from a prefab based on device capabilities. When you change a setting, the sample applies the new value via OVR or URP APIs, waits 0.1 seconds for the platform to stabilize, then rebuilds the UI to reflect the current state.
The Logs panel displays Unity debug logs, warnings, and errors alongside OVRManager lifecycle events in an in-game console, providing immediate visibility into performance warnings and state changes without removing your headset.

Key concepts

Fixed Foveated Rendering control

The sample provides separate controls for static and dynamic FFR. Static FFR applies a fixed foveation level from the OVRPlugin.FoveatedRenderingLevel enum, while dynamic FFR lets the runtime adjust foveation automatically. The FFR effect is visible on the environment but not on the menu panels, since those are rendered as compositor layers.
// From RenderingAndPerf.cs
OVRPlugin.foveatedRenderingLevel = ffrLevel;
OVRPlugin.useDynamicFoveatedRendering = isDynamicFfr;

Two-factor resolution scaling

The sample exposes both XRSettings.eyeTextureResolutionScale and XRSettings.renderViewportScale with separate sliders. The final render resolution is the product of these two values. Lowering either scale reduces GPU load and increases frame rate.
// From RenderingAndPerf.cs
XRSettings.renderViewportScale = viewportScale;
XRSettings.eyeTextureResolutionScale = eyeTextureScale;

Delayed recalculation pattern

After applying performance setting changes, RenderingAndPerf.cs uses WaitAndRecalculate() to pause 0.1 seconds before reading state back from the platform. This delay ensures the OVR runtime has completed its internal updates before the UI queries current values.

Compositor layer UI independence

Both interactive panels are rendered as compositor layers, meaning they bypass the main render pipeline. When you lower resolution scale or increase FFR level, the environment becomes blurrier but the UI panels remain sharp. This pattern is used for critical XR UI elements that must remain readable regardless of rendering quality.

CPU stress testing with the Job System

The CPU utilization controls include a “Use all cores” toggle. When enabled, PushCPUJob distributes 10,000 jobs across worker threads using IJobParallelFor with a batch size of 32. When disabled, the stress test runs a single-threaded loop on the main thread. This contrast highlights the performance advantage of parallel execution for CPU-bound workloads.

Thread-safe logging

LogSection.cs subscribes to Application.logMessageReceivedThreaded, which fires on arbitrary threads. Log entries are buffered in a thread-safe collection and applied to UI TextMeshPro elements during Update() on the main thread, preventing race conditions while maintaining real-time visibility into runtime events.

Extend the sample

  • Add custom performance profiles that save and restore groups of settings with a single button press
  • Integrate OVR Metrics Tool data overlays to display thermal state and sustained frame rate alongside the existing controls
  • Create additional stress tests for physics workloads, shader complexity, or particle systems to identify performance bottlenecks in specific subsystems