Skip to content

Instantly share code, notes, and snippets.

@liamcary
Last active September 26, 2025 19:42
Show Gist options
  • Select an option

  • Save liamcary/fd25f2a4b35553e394ccb6357f054ba7 to your computer and use it in GitHub Desktop.

Select an option

Save liamcary/fd25f2a4b35553e394ccb6357f054ba7 to your computer and use it in GitHub Desktop.
Dynamic Resolution for Oculus Quest with Unity 2021.3 LTS and URP 12
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.XR;
public class DynamicResolutionScaler : MonoBehaviour
{
[SerializeField, Range(0f, 1f)] float _minResolutionScale;
float _lastStepTime;
float _minCooldown;
float _normalizedMinScale;
float _maxResolutionScale;
Vector2Int _recommendedResolution;
const int _pixelStepDown = 256;
const int _pixelStepUp = 128;
const float _stepDownCooldown = 0.25f;
const float _stepUpCooldown = 1f;
void Awake()
{
_maxResolutionScale = (GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset).renderScale;
_normalizedMinScale = _minResolutionScale / _maxResolutionScale;
_minCooldown = Mathf.Min(_stepDownCooldown, _stepUpCooldown);
}
void LateUpdate()
{
float timeSinceLastStep = Time.time - _lastStepTime;
if (timeSinceLastStep < _minCooldown || !TryGetRecommendedResolution(out _recommendedResolution)) {
return;
}
float currentScale = XRSettings.renderViewportScale;
int recommendedWidth = Mathf.Clamp(
_recommendedResolution.x,
(int) (XRSettings.eyeTextureWidth * _normalizedMinScale) - _pixelStepDown,
(int) (XRSettings.eyeTextureWidth * currentScale) + _pixelStepUp
);
float newScale = Mathf.Clamp(recommendedWidth / (float) XRSettings.eyeTextureWidth, _normalizedMinScale, 1f);
if (Mathf.Approximately(currentScale, newScale)) {
return;
}
if ((newScale > currentScale && timeSinceLastStep > _stepUpCooldown) || (newScale < currentScale && timeSinceLastStep > _stepDownCooldown)) {
XRSettings.renderViewportScale = newScale;
_lastStepTime = Time.time;
}
}
bool TryGetRecommendedResolution(out Vector2Int resolution)
{
if (OVRPlugin.GetEyeLayerRecommendedResolution(out var scale)) {
resolution = new Vector2Int(scale.w, scale.h);
return true;
}
resolution = new Vector2Int(XRSettings.eyeTextureWidth, XRSettings.eyeTextureHeight);
return false;
}
}
@DanjelRicci
Copy link

DanjelRicci commented Oct 13, 2024

I found this a couple days ago and ended up using it because at least it seems to work, thanks a lot. I'm on Unity 2022.3.49 and Dynamic Resolution still doesn't work well with URP, in my case it always sets the maximum resolution possible and never goes down, same behavior both with OpenGL and Vulkan. I opened a ticket with Meta and a thread on their developer forums, but I don't have solutions yet.

I'm wondering if you are still using this as it is, or do you have an updated version? Asking just because in my project it seems to catch framerate drops a bit too late than it would be necessary.

@holydel
Copy link

holydel commented Feb 18, 2025

Thanks! Works for me too (vulkan, urp 12, unity 2022.3)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment