├── .gitignore ├── Assets ├── DynamicResolution.meta ├── DynamicResolution │ ├── Prefabs.meta │ ├── Prefabs │ │ ├── FpsResolutionCanvas.prefab │ │ └── FpsResolutionCanvas.prefab.meta │ ├── Scripts.meta │ └── Scripts │ │ ├── DynamicResolution.cs │ │ └── DynamicResolution.cs.meta ├── test.unity └── test.unity.meta ├── DynamicResolution.unitypackage ├── LICENSE ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.csproj 11 | *.unityproj 12 | *.sln 13 | *.suo 14 | *.tmp 15 | *.user 16 | *.userprefs 17 | *.pidb 18 | *.booproj 19 | *.svd 20 | 21 | 22 | # Unity3D generated meta files 23 | *.pidb.meta 24 | 25 | # Unity3D Generated File On Crash Reports 26 | sysinfo.txt 27 | 28 | # Builds 29 | *.apk 30 | #*.unitypackage 31 | -------------------------------------------------------------------------------- /Assets/DynamicResolution.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b78d8bcab55b9c74a8cbd827cbc3ea29 3 | folderAsset: yes 4 | timeCreated: 1485306087 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/DynamicResolution/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65a1ffb3afe64cb4f99c4d9165207eb5 3 | folderAsset: yes 4 | timeCreated: 1485306067 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/DynamicResolution/Prefabs/FpsResolutionCanvas.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/Assets/DynamicResolution/Prefabs/FpsResolutionCanvas.prefab -------------------------------------------------------------------------------- /Assets/DynamicResolution/Prefabs/FpsResolutionCanvas.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 00dddc66939c2a442b5ea6409518c98e 3 | timeCreated: 1479751928 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/DynamicResolution/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 22eb00c6cb1af7a49899df8dea9af189 3 | folderAsset: yes 4 | timeCreated: 1485306067 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/DynamicResolution/Scripts/DynamicResolution.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.UI; 3 | 4 | [RequireComponent(typeof(Text))] 5 | public class DynamicResolution : MonoBehaviour 6 | { 7 | /// 8 | /// Tells if the text has to be visible (true) or not (false). 9 | /// 10 | public bool EnableText = true; 11 | /// 12 | /// Disables everything when true. 13 | /// 14 | public bool DisableResolutionChangesAndEvaluation = false; 15 | /// 16 | /// Overrides the default resolution (1 means normal, 0.9f is 90%, and so on) 17 | /// 18 | public float StartingRatioOverride = 1; 19 | /// 20 | /// Setting to say that the current scene has static resolution (basically disables the script except for StartingRatioOverride) 21 | /// 22 | public bool StaticResolution = false; 23 | /// 24 | /// Setting to decide if the resolution has to be changed based on scene average fps or based on instant fps. 25 | /// 26 | public bool BasedOnSceneAvg = true; 27 | /// 28 | /// Setting to decide how many times a scene can chenge the resolution 29 | /// 0 = false; -1 = true (until minimum); 30 | /// 1 means 1 time, 2 means 2 times and so on. 31 | /// 32 | public int InvokeRecursively = 1; // 0 = false; -1 = true; 1 means 1 time, 2 means 2 times and so on. 33 | /// 34 | /// Setting to tell if the resolution has to be changed at screen change or as soon as possible. 35 | /// Enabled by default since resolution changes are visible. 36 | /// Still changing all the time (false) can be useful if you have a scene dedicate to hardware estimation. 37 | /// 38 | public bool OnlyOnSceneChange = true; 39 | /// 40 | /// Resolution will go lower if FPS (or average FPS ot the scene, depending on settings) drop below this value 41 | /// 42 | public int InferiorFpsLimit = 29; 43 | /// 44 | /// Resolution will go higher if FPS (or average FPS ot the scene, depending on settings) goes above this value 45 | /// 46 | public int SuperiorFpsLimit = 49; 47 | /// 48 | /// Sets the maximum FPS of the scene (60 is usually the maximum allowed on smartphones) 49 | /// 50 | public int TargetFps = 60; 51 | 52 | private const float startingPeriod = 0.5f; 53 | private const float regimePeriod = 2.0f; 54 | private const float avgFpsStartPeriod = 2.0f; // better be a multiple of regimePeriod 55 | private bool startAvg = false; 56 | 57 | private static float fpsMeasurePeriod; 58 | private int fpsAccumulator = 0; 59 | private float fpsNextPeriod = 0; 60 | private int currentFps = 0; 61 | private int avgFpsAccumulator = 0; 62 | private float totalPeriodSinceStart = 0; 63 | private int currentAvgFps = 0; 64 | 65 | private static int lastSceneAvgFps = 0; 66 | 67 | const string display = "{0} FPS - {8} Avg FPS\nResolution at next refresh: {1}x{2}\nOriginal resolution: {3}x{4}\nCurrent res and modifier: {5}x{6} * {7}"; 68 | private Text text; 69 | 70 | 71 | 72 | private static int originalwidth; 73 | private static int originalheight; 74 | private static int currentwidth; 75 | private static int currentheight; 76 | private int minimalwidth; 77 | private int minimalheight; 78 | 79 | public static bool resized { get; private set; } 80 | 81 | void Start() 82 | { 83 | this.gameObject.SetActive(!DisableResolutionChangesAndEvaluation); 84 | 85 | // initialization 86 | resized = resized ? true : false; 87 | fpsMeasurePeriod = startingPeriod; 88 | originalwidth = (originalwidth == 0) ? Screen.width : originalwidth; 89 | originalheight = (originalheight == 0) ? Screen.height : originalheight; 90 | 91 | currentwidth = (currentwidth == 0) ? originalwidth : currentwidth; 92 | currentheight = (currentheight == 0) ? originalheight : currentheight; 93 | 94 | minimalwidth = (int)(originalwidth * 0.69f); 95 | minimalheight = (int)(originalheight * 0.69f); 96 | 97 | float ratioOverride = (!resized) ? StartingRatioOverride : 1; 98 | 99 | fpsNextPeriod = Time.realtimeSinceStartup + fpsMeasurePeriod; 100 | 101 | text = GetComponent(); 102 | 103 | // decisions 104 | if (EnableText) 105 | updateOverlay(); 106 | else 107 | text.text = ""; 108 | 109 | if (ratioOverride != 1 && (!resized || StaticResolution)) resize((int)(currentwidth * ratioOverride), (int)(currentheight * ratioOverride)); 110 | else if (resized && OnlyOnSceneChange) 111 | { 112 | resize(currentwidth, currentheight); 113 | lastSceneAvgFps = 0; 114 | } 115 | if (!StaticResolution) 116 | if (InvokeRecursively == -1 || InvokeRecursively > 0) 117 | { 118 | Invoke("refreshResolution", regimePeriod); 119 | } 120 | } 121 | 122 | void Update() 123 | { 124 | // measuring frames per second in the fpsMeasurePeriod 125 | fpsAccumulator++; 126 | avgFpsAccumulator++; 127 | 128 | if (Time.realtimeSinceStartup > fpsNextPeriod) 129 | { 130 | totalPeriodSinceStart += fpsNextPeriod; 131 | int appFps = currentFps; 132 | currentFps = (int)(fpsAccumulator / fpsMeasurePeriod); 133 | if (appFps > currentFps) 134 | startAvg = true; 135 | fpsAccumulator = 0; 136 | fpsNextPeriod += fpsMeasurePeriod; 137 | 138 | //Debug.Log("Time Since Level Load " + Time.timeSinceLevelLoad); 139 | if (BasedOnSceneAvg) 140 | { 141 | if (startAvg && Time.timeSinceLevelLoad > avgFpsStartPeriod) 142 | { 143 | currentAvgFps = (int)(avgFpsAccumulator / Time.timeSinceLevelLoad); 144 | lastSceneAvgFps = currentAvgFps; 145 | } 146 | else 147 | { 148 | //Debug.Log("Not yet started recording avg fps"); 149 | currentAvgFps = currentFps; 150 | avgFpsAccumulator = (int)(currentAvgFps * Time.timeSinceLevelLoad); 151 | } 152 | } 153 | if (EnableText) 154 | updateOverlay(); 155 | else 156 | text.text = ""; 157 | } 158 | } 159 | 160 | private void resize(int width, int height) 161 | { 162 | UnityEngine.Debug.Log(string.Format("resizing to {0}x{1}", width, height)); 163 | Screen.SetResolution(width, height, true, TargetFps); 164 | resized = true; 165 | } 166 | 167 | private void refreshResolution() 168 | { 169 | // bases resolution change on the selected option, so scene average or current fps 170 | float fpsToUse = (BasedOnSceneAvg) ? (lastSceneAvgFps > 0 ? lastSceneAvgFps : currentAvgFps) : currentFps; 171 | bool changed = false; 172 | if (fpsToUse < InferiorFpsLimit && fpsToUse > 0 && currentheight > minimalheight) 173 | { 174 | float ratio = (resized) ? 0.92f : 0.82f; 175 | currentheight = (int)(currentheight * ratio); 176 | if (currentheight < minimalheight) currentheight = minimalheight; 177 | currentwidth = (int)(currentwidth * ratio); 178 | if (currentwidth < minimalwidth) currentwidth = minimalwidth; 179 | 180 | // if it's realtime dynamic resolution applies the resize 181 | if (!OnlyOnSceneChange) resize(currentwidth, currentheight); 182 | changed = true; 183 | } 184 | else if (resized && fpsToUse >= SuperiorFpsLimit && currentheight < originalheight) 185 | { 186 | currentheight = (int)(currentheight * 1.1f); 187 | if (currentheight > originalheight) currentheight = originalheight; 188 | currentwidth = (int)(currentwidth * 1.1f); 189 | if (currentwidth > originalwidth) currentwidth = originalwidth; 190 | 191 | // if it's realtime dynamic resolution applies the resize 192 | if (!OnlyOnSceneChange) resize(currentwidth, currentheight); 193 | changed = true; 194 | } 195 | 196 | resized = true; 197 | 198 | if (InvokeRecursively > 0 && changed) 199 | { 200 | InvokeRecursively--; 201 | changed = false; 202 | } 203 | if (InvokeRecursively == -1 || InvokeRecursively > 0) 204 | { 205 | Invoke("refreshResolution", regimePeriod); 206 | } 207 | } 208 | 209 | private void updateOverlay() 210 | { 211 | string settingsString = "\nMode: " + 212 | (OnlyOnSceneChange ? "only at scene change" : "can change during scene") + 213 | " " + 214 | (InvokeRecursively == -1 ? "recursively" : (InvokeRecursively + " times") + 215 | "\n " + 216 | (BasedOnSceneAvg ? "based on scene average":"")); 217 | text.text = string.Format(display + settingsString, 218 | currentFps, currentwidth, currentheight, originalwidth, originalheight, Screen.width, Screen.height, 219 | !resized ? StartingRatioOverride : 1, currentAvgFps); 220 | Debug.Log(text.text); 221 | } 222 | } 223 | 224 | -------------------------------------------------------------------------------- /Assets/DynamicResolution/Scripts/DynamicResolution.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d564e577a8647684fa6591bbe900b4cc 3 | timeCreated: 1479735293 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/test.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/Assets/test.unity -------------------------------------------------------------------------------- /Assets/test.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 237079c7595e6cf42b799d92e34a92fc 3 | timeCreated: 1485307711 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /DynamicResolution.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/DynamicResolution.unitypackage -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Gaetano Bonofiglio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.5.0f3 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kidel/DynamicResolution-for-Unity3D/bc45c4652fd952d45873920df76e733658d938f3/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dynamic Resolution for Unity 3D 2 | Dynamic Screen Resolution script for constant framerates in Unity 3D games. 3 | 4 | This is the script we used for [Cubic Space](https://play.google.com/store/apps/details?id=com.cubicspace.mcpals) to keep 30+ fps on almost every Android phone. 5 | 6 | :copyright: 2016 Gaetano Bonofiglio, MIT License. 7 | --------------------------------------------------------------------------------