Search code examples
androidiosunity-game-enginescreen-resolution

How to adjust the screen for portrait and landscape mode such that all UI elements can be seen?


I am building an app.I have kept my reference resolution game view setting as (800 x 1200) .Settings for canvas shown below Canvas settings When I check the it Iphone6(750 x 1334) resolution I can see the contents but certain components are cropped with respect to width.The Game view is shown below. I use panels,vertical layout group,horizontal layout group many UI components in my application.

Iphone6 resolution()750 x 1334

Now I changed my Game view resolution to ipad pro(2224 x 1668).Now I cannot see my images.The Game view is shown below Ipad pro resolution (2224 x 1668)

I dont know how to adjust the UI elements according to different screen sizes.Some of the answers I observed was I should keep settings as Scale with screen size,match width or height and Match slider to 0.5. I have kept these settings(see first image).Still it is not changing according to different screen sizes.

I tried Aspect ratio fitter inside the parent element(Showdata) but of no use.What should I do to change screen according to different screen sizes?Is it because I am not anchoring UI elements in a proper way? How will you anchor something like this(Canvas>Panel(Stretched along XY)>Panel(with Vertical layout)>Many UI elements)

I have seen many tutorials on how to use anchor for images and buttons but how to use for nested elements or when we use vertical or horizontal layout and it contains many UI elements.

The Rect Transform for each UI element is given below. Hierarchy


Solution

  • Here is an abbreviated list of tips, from most to least urgent:

    • Set your canvas scaling to Constant Physical Size. On iPhone X devices, the scaling factor is 3x. Find other physical scale factors here. The purpose of doing this is to make your Canvas's layout coordinates correspond to device points while rendering at the native resolution of the device. This is the most urgent source of your agony.
    • For RectTransform components corresponding to a full screen, set its anchors to (0, 0), (1, 1), i.e., fill the parent. Play with the Top, Right, etc. properties. But it seems like you already know that.
    • Child elements of vertical / horizontal layout groups should have a LayoutElement and should generally be of fixed size in the non-scrolling axis, i.e., do not use ContentSizeFitter on rows for now, get it to work for a fixed height. This is almost always the correct behavior on mobile devices anyhow.
    • Experiment with LayoutElement's Ignore Layout flag.
    • Correctly set the Pixels Per Unit setting on your textures.
    • On mobile devices, you will miss issues like cutouts and bevels in corners. Use NotchSolution for Unity 2019.2 and earlier, and the new Device Simulator for 2019.3 and above, to visualize and adapt to these issues.
    • Use a recycling scroll view component, like Optimized ScrollView Adapter. This will also include thoughtful tutorials about how to lay things out. If you need content fit height elements in a recycling scroll view, you will need this asset.
    • To generally trigger changes based on screen layout, use OnRectTransformDimensionsChanged(). Nothing else, don't check for changes in Screen! You should familiarize yourself with the EventSystem generally.
    • Familiarize yourself with the aspect ratios of various devices, and use Camera.main.aspect to correctly toggle between hand-tuned layouts for these aspect ratios. There are 4 in iOS.

    Here is an example of a platform canvas scaler:

    using UnityEngine;
    using UnityEngine.EventSystems;
    #if UNITY_IPHONE
    using UnityEngine.iOS;
    #endif
    using UnityEngine.UI;
    
    namespace StackOverflow
    {
        [ExecuteInEditMode]
        public sealed class PlatformCanvasScaler : UIBehaviour
        {
            public static PlatformCanvasScaler instance { get; private set; }
    
    
            public float scaleFactor
            {
                get
                {
                    if (m_CanvasScaler != null)
                    {
                        return m_CanvasScaler.scaleFactor;
                    }
    
                    return 1.0f;
                }
            }
    
            [SerializeField] private CanvasScaler m_CanvasScaler;
            [SerializeField] private float m_PhoneScaleFactor = 1.15f;
    
            private PlatformCanvasScaler()
            {
                instance = this;
            }
    
            protected override void Awake()
            {
                base.Awake();
    
                if (!enabled)
                {
                    return;
                }
    
                Refresh();
            }
    
            private void Refresh()
            {
                var scaleFactor = 1f;
                var isMobile = PlatformCanvasScaler.isMobile;
                if (isMobile)
                {
    #if UNITY_IPHONE
                    switch (Device.generation)
                    {
                        case DeviceGeneration.iPhoneX:
                        case DeviceGeneration.iPhoneXSMax:
                        case DeviceGeneration.Unknown:
                        case DeviceGeneration.iPadUnknown:
                        case DeviceGeneration.iPodTouchUnknown:
                            scaleFactor = 3f;
                            break;
                        case DeviceGeneration.iPhone5:
                        case DeviceGeneration.iPhoneSE1Gen:
                        case DeviceGeneration.iPhone5C:
                        case DeviceGeneration.iPhone5S:
                        case DeviceGeneration.iPhone6:
                        case DeviceGeneration.iPhone6S:
                        case DeviceGeneration.iPhone7:
                        case DeviceGeneration.iPhone8:
                        case DeviceGeneration.iPhoneXR:
                        case DeviceGeneration.iPhoneUnknown:
                            scaleFactor = 2f;
                            break;
                        case DeviceGeneration.iPhone6Plus:
                        case DeviceGeneration.iPhone7Plus:
                        case DeviceGeneration.iPhone8Plus:
                        case DeviceGeneration.iPhone6SPlus:
                            scaleFactor = 3f / 1.15f;
                            break;
                        case DeviceGeneration.iPhone:
                        case DeviceGeneration.iPhone3G:
                        case DeviceGeneration.iPhone3GS:
                        case DeviceGeneration.iPad1Gen:
                        case DeviceGeneration.iPad2Gen:
                        case DeviceGeneration.iPad3Gen:
                            scaleFactor = 1f;
                            break;
                        default:
                            scaleFactor = 2f;
                            break;
                    }
    
                    scaleFactor *= m_PhoneScaleFactor;
    #else
                    scaleFactor = 2f * Screen.dpi / 326f;
    #endif
                }
                else
                {
                    if (Screen.dpi > 140)
                    {
                        scaleFactor = 2.0f;
                    }
                    else
                    {
                        scaleFactor = 1.0f;
                    }
                }
    
                m_CanvasScaler.scaleFactor = scaleFactor;
            }
    
            public static bool isMobile
            {
                get
                {
                    var isPhone = false;
    #if UNITY_IPHONE
                    isPhone = true;
    #endif
                    var isMobile = Application.platform == RuntimePlatform.IPhonePlayer ||
                                   (Application.isEditor && isPhone);
                    return isMobile;
                }
            }
    
    #if UNITY_EDITOR
            private void OnValidate()
            {
                Refresh();
            }
    #endif
    
            // Update is called once per frame
            private void Update()
            {
            }
        }
    }
    

    Observe I make some decisions about what is considered a HiDPI device.

    Unfortunately, my favorite UI asset for screen management, MaterialUI, is deprecated. Hopefully someone can comment on their experience with others.