3 using System.Collections.Generic;
18 [Tooltip(
"The minimum frame time percentage threshold used to increase render quality.")]
19 private float MinFrameTimeThreshold = 0.75f;
22 [Tooltip(
"The maximum frame time percentage threshold used to decrease render quality.")]
23 private float MaxFrameTimeThreshold = 0.95f;
26 private int MinQualityLevel = -5;
28 private int MaxQualityLevel = 5;
30 private int StartQualityLevel = 5;
32 public delegate
void QualityChangedEvent(
int newQuality,
int previousQuality);
35 public int QualityLevel {
get;
private set; }
36 public int RefreshRate {
get;
private set; }
38 private float frameTimeQuota;
43 private const int maxLastFrames = 7;
44 private Queue<float> lastFrames =
new Queue<float>();
46 private const int minFrameCountBeforeQualityChange = 5;
47 private int frameCountSinceLastLevelUpdate;
50 private Camera adaptiveCamera;
52 public const string TimingTag =
"Frame";
54 private void OnEnable()
56 QualityLevel = StartQualityLevel;
60 #if UNITY_2017_2_OR_NEWER 61 RefreshRate = (int)
UnityEngine.XR.XRDevice.refreshRate;
63 RefreshRate = (
int)
UnityEngine.VR.VRDevice.refreshRate;
68 if (!Application.isEditor)
70 Debug.LogWarning(
"Could not retrieve the HMD's native refresh rate. Assuming " + RefreshRate +
" Hz.");
73 frameTimeQuota = 1.0f / RefreshRate;
76 if (adaptiveCamera == null)
78 adaptiveCamera = Camera.main;
83 if (gpuCamera == null || gpuCamera.
TimingTag.CompareTo(TimingTag) != 0)
91 UpdateAdaptiveQuality();
94 private bool LastFramesBelowThreshold(
int frameCount)
97 if (lastFrames.Count < frameCount || frameCountSinceLastLevelUpdate < frameCount)
102 float maxTime = frameTimeQuota * MinFrameTimeThreshold;
104 foreach (var frameTime
in lastFrames)
106 if (frameTime >= maxTime)
115 private void UpdateQualityLevel(
int delta)
118 int prevQualityLevel = QualityLevel;
119 QualityLevel = Mathf.Clamp(QualityLevel + delta, MinQualityLevel, MaxQualityLevel);
122 if (QualityLevel != prevQualityLevel)
124 if (QualityChanged != null)
126 QualityChanged(QualityLevel, prevQualityLevel);
128 frameCountSinceLastLevelUpdate = 0;
132 private void UpdateAdaptiveQuality()
136 if (lastAppFrameTime <= 0)
142 lastFrames.Enqueue(lastAppFrameTime);
143 if (lastFrames.Count > maxLastFrames)
145 lastFrames.Dequeue();
149 frameCountSinceLastLevelUpdate++;
150 if (frameCountSinceLastLevelUpdate < minFrameCountBeforeQualityChange)
156 if (lastAppFrameTime > MaxFrameTimeThreshold * frameTimeQuota)
158 UpdateQualityLevel(-2);
160 else if (lastAppFrameTime < MinFrameTimeThreshold * frameTimeQuota)
163 if (LastFramesBelowThreshold(maxLastFrames))
165 UpdateQualityLevel(1);