- Home /
Add and Select Game View Resolution Programatically
How can I add and select resolution programmatically in Game View without Free Aspect. (I Need editor Script )
1-) I want to add new resolution
2-) Select this resolution
Answer by vexe · May 01, 2015 at 03:16 AM
There you go, pretty straight forward :)
using System;
using UnityEditor;
using UnityEngine;
public static class Utils
{
public enum GameViewSizeType
{
AspectRatio, FixedResolution
}
[MenuItem("Test/AddSize")]
public static void AddTestSize()
{
AddCustomSize(GameViewSizeType.AspectRatio, GameViewSizeGroupType.Standalone, 123, 456, "Test size");
}
public static void AddCustomSize(GameViewSizeType viewSizeType, GameViewSizeGroupType sizeGroupType, int width, int height, string text)
{
// goal:
// var group = ScriptableSingleton<GameViewSizes>.instance.GetGroup(sizeGroupType);
// group.AddCustomSize(new GameViewSize(viewSizeType, width, height, text);
var asm = typeof(Editor).Assembly;
var sizesType = asm.GetType("UnityEditor.GameViewSizes");
var singleType = typeof(ScriptableSingleton<>).MakeGenericType(sizesType);
var instanceProp = singleType.GetProperty("instance");
var getGroup = sizesType.GetMethod("GetGroup");
var instance = instanceProp.GetValue(null, null);
var group = getGroup.Invoke(instance, new object[] { (int)sizeGroupType });
var addCustomSize = getGroup.ReturnType.GetMethod("AddCustomSize"); // or group.GetType().
var gvsType = asm.GetType("UnityEditor.GameViewSize");
var ctor = gvsType.GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(string) });
var newSize = ctor.Invoke(new object[] { (int)viewSizeType, width, height, text });
addCustomSize.Invoke(group, new object[] { newSize });
}
}
[EDIT] Here's a version that performing size queries and setting the current size as per Mr Naphier request in the comments.
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
public static class GameViewUtils
{
static object gameViewSizesInstance;
static MethodInfo getGroup;
static GameViewUtils()
{
// gameViewSizesInstance = ScriptableSingleton<GameViewSizes>.instance;
var sizesType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizes");
var singleType = typeof(ScriptableSingleton<>).MakeGenericType(sizesType);
var instanceProp = singleType.GetProperty("instance");
getGroup = sizesType.GetMethod("GetGroup");
gameViewSizesInstance = instanceProp.GetValue(null, null);
}
public enum GameViewSizeType
{
AspectRatio, FixedResolution
}
[MenuItem("Test/AddSize")]
public static void AddTestSize()
{
AddCustomSize(GameViewSizeType.AspectRatio, GameViewSizeGroupType.Standalone, 123, 456, "Test size");
}
[MenuItem("Test/SizeTextQuery")]
public static void SizeTextQueryTest()
{
Debug.Log(SizeExists(GameViewSizeGroupType.Standalone, "Test size"));
}
[MenuItem("Test/Query16:9Test")]
public static void WidescreenQueryTest()
{
Debug.Log(SizeExists(GameViewSizeGroupType.Standalone, "16:9"));
}
[MenuItem("Test/Set16:9")]
public static void SetWidescreenTest()
{
SetSize(FindSize(GameViewSizeGroupType.Standalone, "16:9"));
}
[MenuItem("Test/SetTestSize")]
public static void SetTestSize()
{
int idx = FindSize(GameViewSizeGroupType.Standalone, 123, 456);
if (idx != -1)
SetSize(idx);
}
public static void SetSize(int index)
{
var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView");
var selectedSizeIndexProp = gvWndType.GetProperty("selectedSizeIndex",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var gvWnd = EditorWindow.GetWindow(gvWndType);
selectedSizeIndexProp.SetValue(gvWnd, index, null);
}
[MenuItem("Test/SizeDimensionsQuery")]
public static void SizeDimensionsQueryTest()
{
Debug.Log(SizeExists(GameViewSizeGroupType.Standalone, 123, 456));
}
public static void AddCustomSize(GameViewSizeType viewSizeType, GameViewSizeGroupType sizeGroupType, int width, int height, string text)
{
// GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupTyge);
// group.AddCustomSize(new GameViewSize(viewSizeType, width, height, text);
var group = GetGroup(sizeGroupType);
var addCustomSize = getGroup.ReturnType.GetMethod("AddCustomSize"); // or group.GetType().
var gvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize");
var ctor = gvsType.GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(string) });
var newSize = ctor.Invoke(new object[] { (int)viewSizeType, width, height, text });
addCustomSize.Invoke(group, new object[] { newSize });
}
public static bool SizeExists(GameViewSizeGroupType sizeGroupType, string text)
{
return FindSize(sizeGroupType, text) != -1;
}
public static int FindSize(GameViewSizeGroupType sizeGroupType, string text)
{
// GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupType);
// string[] texts = group.GetDisplayTexts();
// for loop...
var group = GetGroup(sizeGroupType);
var getDisplayTexts = group.GetType().GetMethod("GetDisplayTexts");
var displayTexts = getDisplayTexts.Invoke(group, null) as string[];
for(int i = 0; i < displayTexts.Length; i++)
{
string display = displayTexts[i];
// the text we get is "Name (W:H)" if the size has a name, or just "W:H" e.g. 16:9
// so if we're querying a custom size text we substring to only get the name
// You could see the outputs by just logging
// Debug.Log(display);
int pren = display.IndexOf('(');
if (pren != -1)
display = display.Substring(0, pren-1); // -1 to remove the space that's before the prens. This is very implementation-depdenent
if (display == text)
return i;
}
return -1;
}
public static bool SizeExists(GameViewSizeGroupType sizeGroupType, int width, int height)
{
return FindSize(sizeGroupType, width, height) != -1;
}
public static int FindSize(GameViewSizeGroupType sizeGroupType, int width, int height)
{
// goal:
// GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupType);
// int sizesCount = group.GetBuiltinCount() + group.GetCustomCount();
// iterate through the sizes via group.GetGameViewSize(int index)
var group = GetGroup(sizeGroupType);
var groupType = group.GetType();
var getBuiltinCount = groupType.GetMethod("GetBuiltinCount");
var getCustomCount = groupType.GetMethod("GetCustomCount");
int sizesCount = (int)getBuiltinCount.Invoke(group, null) + (int)getCustomCount.Invoke(group, null);
var getGameViewSize = groupType.GetMethod("GetGameViewSize");
var gvsType = getGameViewSize.ReturnType;
var widthProp = gvsType.GetProperty("width");
var heightProp = gvsType.GetProperty("height");
var indexValue = new object[1];
for(int i = 0; i < sizesCount; i++)
{
indexValue[0] = i;
var size = getGameViewSize.Invoke(group, indexValue);
int sizeWidth = (int)widthProp.GetValue(size, null);
int sizeHeight = (int)heightProp.GetValue(size, null);
if (sizeWidth == width && sizeHeight == height)
return i;
}
return -1;
}
static object GetGroup(GameViewSizeGroupType type)
{
return getGroup.Invoke(gameViewSizesInstance, new object[] { (int)type });
}
}
[MenuItem("Test/LogCurrentGroupType")]
public static void LogCurrentGroupType()
{
Debug.Log(GetCurrentGroupType());
}
public static GameViewSizeGroupType GetCurrentGroupType()
{
var getCurrentGroupTypeProp = gameViewSizesInstance.GetType().GetProperty("currentGroupType");
return (GameViewSizeGroupType)(int)getCurrentGroupTypeProp.GetValue(gameViewSizesInstance, null);
}
@Naphier I'm a bit busy atm but if you just get ILSpy and open Editor/Data/$$anonymous$$anaged/UnityEngine.dll and do some very simple investigation you'll find what you're looking for!
@Naphier so you just want a list/array of the currently available game view sizes?
By set you mean 'add' and not setting the whole array to a new value right? from what I've gathered, you're just missing a query on a certain size existence before using AddCustomSize, right? i.e. if (!SizeExists(mySize)) AddCustomSize(etc);
@Naphier I found a method that returns the display text of sizes, we could easily use that to see if a custom size exist or not - does that work for you or is querying sizes by text out of the picture for you?
If you are using .net 4.x you must do these changes:
var gvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize");
var ctor = gvsType.GetConstructor(new Type[] { typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeType"), typeof(int), typeof(int), typeof(string) });
var newGvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeType");
if (gameViewSizeType == GameViewSizeType.AspectRatio)
{
newGvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeType.AspectRatio");
}
else
{
newGvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeType.FixedResolution");
}
var newSize = ctor.Invoke(new object[] { newGvsType, width, height, name });
addCustomSize.Invoke(group, new object[] { newSize });
Answer by kasskata · Nov 02, 2016 at 12:19 PM
After v5.4 (zoom added) you will have issues with Canvas size scaler. To do it propperly you must call other method attached on every element from size dropdown list called "SizeSelectionCallback"
public static void SetSize(int index)
{
var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView");
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var gvWnd = EditorWindow.GetWindow(gvWndType);
var SizeSelectionCallback = gvWndType.GetMethod("SizeSelectionCallback",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
SizeSelectionCallback.Invoke(gvWnd, new object[] {index,null});
}
Just call that method from your editor script and give proper index. (Sorry about my bad english).
I think you missed some code there, the line that's just flags makes it not compile. I find that in 5.6 with iOS utility added, both code suggestions just cause the resolution to get set to the nearest iOS resolution. It's working fine in 5.4 and I also have iOS component installed for that too. Investigating
EDIT: Oops, I had my build target set to iOS. Changing to standalone fixed it. I tried both suggested SetSize methods and didn't notice any difference, what extra zoom slider functionality is this new SetSize code supposed to add?
Ok. I will give you entire script. Works for me all the time. Hope will help you. :)
public class GameViewUtils
{
static object gameViewSizesInstance;
static $$anonymous$$ethodInfo getGroup;
private static int screenIndex = 16; // Because have 16 indexes in my list.
private static int gameViewProfilesCount;
static GameViewUtils()
{
// gameViewSizesInstance = ScriptableSingleton<GameViewSizes>.instance;
var sizesType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizes");
var singleType = typeof(ScriptableSingleton<>).$$anonymous$$akeGenericType(sizesType);
var instanceProp = singleType.GetProperty("instance");
getGroup = sizesType.Get$$anonymous$$ethod("GetGroup");
gameViewSizesInstance = instanceProp.GetValue(null, null);
}
private enum GameViewSizeType
{
AspectRatio, FixedResolution
}
private static void SetSize(int index)
{
var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView");
var gvWnd = EditorWindow.GetWindow(gvWndType);
var SizeSelectionCallback = gvWndType.Get$$anonymous$$ethod("SizeSelectionCallback",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
SizeSelectionCallback.Invoke(gvWnd, new object[] { index, null });
}
static object GetGroup(GameViewSizeGroupType type)
{
return getGroup.Invoke(gameViewSizesInstance, new object[] { (int)type });
}
[$$anonymous$$enuItem("Tools/GameViewSize/Previous %&Q")]
private static void SetPrevious()
{
GetViewListSize();
if (screenIndex - 1 >= 16)
{
screenIndex -= 1;
}
else
{
screenIndex = gameViewProfilesCount - 1;
}
SetSize(screenIndex);
}
[$$anonymous$$enuItem("Tools/GameViewSize/Next %&E")]
private static void SetNext()
{
GetViewListSize();
if (screenIndex + 1 < gameViewProfilesCount)
{
screenIndex += 1;
}
else
{
screenIndex = 16;
}
SetSize(screenIndex);
}
private static void GetViewListSize()
{
var group = GetGroup(GameViewSizeGroupType.Android);
var getDisplayTexts = group.GetType().Get$$anonymous$$ethod("GetDisplayTexts");
gameViewProfilesCount = (getDisplayTexts.Invoke(group, null) as string[]).Length;
}
}
Answer by Wappenull · Apr 10, 2021 at 12:18 PM
I'm making this into keyboard shortcut version.
But without the adding custom resolution part. Because why bother do it via script while you can do it easily on GUI.
ALT+1 = 1280x720 (not added by default, you have to add it manually to work) ALT+2 = 1920x1080 ALT+3 = 2560x1440
It is global shortcut key, and will be shown in "Edit > Shortcuts" menu.
To change the resolution the key is taking, you must modify the hard code.
https://gist.github.com/wappenull/668a492c80f7b7fda0f7c7f42b3ae0b0
Answer by chris_tmssn · Jun 22, 2017 at 09:25 AM
just find this post... first of all realy good script, but i've discovered a problem. adding new resolutions works just fine but when i close the project and open it up again the added resolutions are gone :( what am i doing wrong?
I don't have that problem with disappearing resolutions list. $$anonymous$$aybe is another issue from Unity. Don't know. Sorry.
I realize this may or not be a viable solution for you. Also, this post is pretty old...
I'm using this effectively in 2018.2, however, I experienced this issue you've mentioned. One workaround is to programmatically add them by using this script, then add a custom one through the UI. This saved all the generated ones. You can safely delete the custom test one and the other will persist.
Anyone know how to completely clear out all of the custom menu sizes in script without having to do it manually?
hey @chris_tmssn I know it has being 2 years since you asked. But if anyone else discover this problem, the solution is to call SaveToHDD in GameViewSizes.
sizesType.Get$$anonymous$$ethod("SaveToHDD").Invoke(gameViewSizesInstance, null);
Answer by SimonMV · Nov 25, 2020 at 10:48 AM
Hi the AddCustomSize method did not work (anymore) in Unity 2019.4. I had to change it to the following method taken from https://forum.unity.com/threads/add-game-view-resolution-programatically-old-solution-doesnt-work.860563/
public static void AddCustomSize(GameViewSizeType viewSizeType, GameViewSizeGroupType sizeGroupType, int width, int height, string text)
{
var group = GetGroup(sizeGroupType);
var addCustomSize = getGroup.ReturnType.GetMethod("AddCustomSize"); // or group.GetType().
var gvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize");
string assemblyName = "UnityEditor.dll";
Assembly assembly = Assembly.Load(assemblyName);
Type gameViewSize = assembly.GetType("UnityEditor.GameViewSize");
Type gameViewSizeType = assembly.GetType("UnityEditor.GameViewSizeType");
ConstructorInfo ctor = gameViewSize.GetConstructor(new Type[]
{
gameViewSizeType,
typeof(int),
typeof(int),
typeof(string)
});
var newSize = ctor.Invoke(new object[] { (int)viewSizeType, width, height, text });
addCustomSize.Invoke(group, new object[] { newSize });
}