Search Unity

Canvas scaler issues with iPhone X

Discussion in 'iOS and tvOS' started by adamt, Nov 22, 2017.

  1. adamt

    adamt

    Joined:
    Apr 1, 2014
    Posts:
    116
    Our game uses a Canvas Scaler to accommodate most common device resolutions/aspect ratios (16:9 and 4:3). Unfortunately, with the advent of the iPhone X, it's throwing our scaler out of whack. Here are our settings:
    • UI Scale Mode: Scale With Screen Size
    • Reference Resolution: 1334 x 750 (iPhone 6/7 resolution)
    • Screen Match Mode: Match Width or Height
    • Match: 0
    • Reference Pixels Per Unit: 100
    The game looks like this with these settings applied:

    1334x750.png
    1334x750 (iPhone, 16:9)

    1024x768.png
    1024x768 (iPad, 4:3) -- notice the extra room on the top since we match to the width

    Here's the view on the iPhone X (using its safe area of 2172x1062):

    2172x1062.png
    2172x1062 (iPhone X "safe area", 18.4:9) -- notice the top and bottom are cut off

    I've tried setting the match to 0.5 but the top and bottom are still clipped on the iPhone X. I also tried to anchor our UI screens to the extents of the screen (currently they're anchored to the center of the screen and extend outward) which generally works, but they become way too large on the iPad (see screenshot below). The centered look in the above screenshots is much more easy to manage so we don't have to stretch sub-game objects (like the container for the player's item cards, in the screenshots).

    Does anyone have any advice on how best to make these UIs look good across all aspect ratios?

    P.S. Here's the stretched iPad screenshot to show how it's not really ideal:

    1024x768 stretched.png
     
    Last edited: Nov 22, 2017
  2. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Our trick of fixing that problem is to change the canvas scaler for the different devices. In your case changing match to 1 for the iPhone X should solve your problem. :)
     
  3. adamt

    adamt

    Joined:
    Apr 1, 2014
    Posts:
    116
    Interesting, I think that'd work. Are you using any iPhone X-specific checks for this, do you have something that's kind of a sliding scale on the match percentage based on the aspect ratio, or are you doing something more like this:

    if(camera.aspect > 2.0f) scaler.matchWidthOrHeight = 1.0f;
     
  4. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    I'm doing it like this:
    upload_2017-11-22_19-4-30.png

    In the end I guess it is kind of an overkill, but that way I have complete control. If the device is not saved in the list, I'm using the aspect ratio, kind of like you proposed it :)
     
    protopop and Gametyme like this.
  5. chrisj7w

    chrisj7w

    Joined:
    Jul 31, 2017
    Posts:
    3

    How did you set up the devicesettings or access it? I'm assuming you created it custom as I can't find anything like it. Also i'm pretty new to unity and in need of your direction :)
     
    BTStudios likes this.
  6. adamt

    adamt

    Joined:
    Apr 1, 2014
    Posts:
    116
    Wow, nice work, @Johannski. I think I'm going to do something a bit less polished than your solution (just posting this here to help anyone else out, and maybe also to find any holes that others who read this can see):
    1. Set the "match" field on the root canvas's Canvas Scaler based on the device resolution (basically I'm always using 0 here unless I find an iPhone X, when I set it to 1 instead);
    2. Add a new GameObject as a child of the root canvas that stretches to fill the entire canvas. This will effectively be our new container object for all UI objects (whereas the root canvas was previously). If an iPhone X is detected, it'll nudge the left edge of the this GameObject's bounds inward 90 pixels to clear the notch, and up 10 pixels to clear the "handle" at the bottom of the screen. This gives us the benefit of the playing field extending into the horns and the handle but the UI staying out.
    I'd also considered completely clearing the notch and horns entirely (just pillarboxing them with black) but it looks kinda weird to shift the game over on the left edge and not on the right.
     
  7. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,561
    That's beautiful.

    I have all my device codes hard coded, but I'm going to make a flexible component like this to replace that.

    Thanks for the inspiration :)
     
  8. BTStudios

    BTStudios

    Joined:
    Aug 26, 2017
    Posts:
    2
    Hey mate! I love the look of this and the control per device! How did you set this up? If you could point me in the right direction that'd be awesome.
     
  9. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Alrighty, here is a quick overview:
    Using a scriptableObject, because all of this is just data.
    This scriptable object has a controller for every platform:
    This is just pseudo code to give you an idea of how I implemented the basic structure.
    Code (CSharp):
    1. public class DeviceSettings : ScriptableObject, IQualitySetting
    2.     {
    3. #if UNITY_EDITOR
    4.         public enum Platform
    5.         {
    6.             Ios,
    7.             TvOS,
    8.             Android,
    9.             Standalone
    10.         }
    11.  
    12.         [SerializeField]
    13.         private Platform simulatedPlatform = Platform.Ios;
    14. #endif
    15.  
    16.         [SerializeField]
    17.         private IosDeviceSettings iosSettings = new IosDeviceSettings();
    18.         [SerializeField]
    19.         private TvOsDeviceSettings tvOsSettings = new TvOsDeviceSettings();
    20.         [SerializeField]
    21.         private AndroidDeviceSettings androidSettings = new AndroidDeviceSettings();
    22.         [SerializeField]
    23.         private StandaloneDeviceSettings standaloneSettings = new StandaloneDeviceSettings();
    24.  
    25.         public IosDeviceSettings IosSettings
    26.         {
    27.             get { return iosSettings; }
    28.         }
    29.  
    30.         public TvOsDeviceSettings TvOsSettings
    31.         {
    32.             get { return tvOsSettings; }
    33.         }
    34.  
    35.         public AndroidDeviceSettings AndroidSettings
    36.         {
    37.             get { return androidSettings; }
    38.         }
    39.  
    40.         public StandaloneDeviceSettings StandaloneSettings
    41.         {
    42.             get { return standaloneSettings; }
    43.         }
    44.  
    45.         private IQualitySetting qualitySettingController;
    46.         private bool initialized;
    47.  
    48.         public void Initialize()
    49.         {
    50.             qualitySettingController = GetQualitySettingController();
    51.             qualitySettingController.Initialize();
    52.             initialized = true;
    53.         }
    54.  
    55.         private IQualitySetting GetQualitySettingController()
    56.         {
    57.  
    58. #if UNITY_EDITOR
    59.             switch (simulatedPlatform)
    60.             {
    61.                 case Platform.Ios:
    62.                     return iosSettings;
    63.                 case Platform.TvOS:
    64.                     return tvOsSettings;
    65.                 case Platform.Android:
    66.                     return androidSettings;
    67.                 default:
    68.                     return standaloneSettings;
    69.             }
    70. #elif UNITY_IOS
    71.             return iosSettings;
    72. #elif UNITY_TVOS
    73.             return tvOsSettings;
    74. #elif UNITY_ANDROID
    75.             return androidSettings;
    76. #else
    77.             return standaloneSettings;
    78. #endif
    79.         }
    80.  
    81.         public QualitySetting GetQualitySetting()
    82.         {
    83.             if (!initialized)
    84.             {
    85.                 Initialize();
    86.             }
    87.             return qualitySettingController.GetQualitySetting();
    88.         }
    89.  
    90.         public DeviceNameMapping GetSettings()
    91.         {
    92.             return qualitySettingController.GetSettings();
    93.         }
    94.     }
    We're developing an iOS game, so the thing I focused the most on is the implementation of IosDeviceSettings. For iOS every device has its own model name, you can get it with var modelName = SystemInfo.deviceModel;. For a mapping of all those model names take a look at https://www.theiphonewiki.com/wiki/Models (The identifier column is the one interesting for you).
    I'm also storing the resolution of those devices so I can automatically add an iPhoneX overlay to the editor when I'm working with that resolution.

    As for android, I wouldn't go with that approach, but with a more broad solution. Maybe a combination of resolution CPU and GPU do define what setting should be used. You could of course also add specific devices that should be checked beforehand in order to be able to fix problems on single devices :)

    Hope this helps you steer in the right direction!

    @protopop Thanks for the kind words!
     
    Last edited: Jul 11, 2018
  10. julioteodori

    julioteodori

    Joined:
    Aug 12, 2014
    Posts:
    2
    To Johannski
    Would it be possible to have your email to make a proffesinal question by sending an image adapted to the iPhone X? Without the image it is difficult to explain and since it is from a game that is already in Apple Review we can not publish it yet in the Forum of Unity. Thanks a lot! Belber Games
    Please you can visit our website to know about the game.
    www.belbergames.com
     
    Last edited: Feb 27, 2018
  11. SpaceRay

    SpaceRay

    Joined:
    Feb 26, 2014
    Posts:
    455
    Hello Johannski, I have also the problem of a game that must be adapted for iPhone X, as it seems that the UI works correctly for iPhone 8 but not at all for iPhone X as the UI is over the safe area

    I have copied the script that you have put but I get a lot of errors as seen on the screenshot below, I think is because there may be something missing or an additional script reference.

    Please can you be so kind to help to fix it if possible?

    Thanks very much
     

    Attached Files:

  12. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    @julioteodori I send you a PM :)

    @SpaceRay: The code I shared is more like pseudo code. It gives you an idea on how my structure is, but nothing to copy paste. As for the complete code, I would need to do quite a bit or rewriting since it uses or own Quality Assurance System as well as functionality from Odin Inspector. If there is enough interest for it, I might create an asset from it. Otherwise you will need to create it yourself from the overview I gave.
     
    SpaceRay likes this.
  13. SpaceRay

    SpaceRay

    Joined:
    Feb 26, 2014
    Posts:
    455
    Thanks very much for your answer and explaining it. I already thought that it should be some kind of custom inspector and I was right.

    I have tried to send you a PM but it seems that you have it disabled? As the start conversation is not available.

    If I buy Odin Inspector, would I be able to pay you for having this custom script you have made using Odin, so this way you do not need any rewriting. Tell me it through PM.

    What I need is that to be able to identify the following devices
    iPhone X
    iPhone 8
    iPad mini
    iPad 9,7"
    and apply custom different Canvas Scaler settings for each device, so each one can have independently custom UI sizes and can then resize the UI for each one, although maybe I am wrong and it may not work this way.

    My current Project game is for iOS only now, but in the near future I will also use TVOS and Android for our game.

    Thanks very much for your help. Much appreciated any help with this.
     
    Last edited: Feb 27, 2018
  14. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826

    Whoops, didn't even know I did that, thanks for pointing it out. Just wanted to send you a PM, but apparently you disabled it as well ^^ (You can find it in the Privacy settings under "Start conversations with you").
    Odin is not necessarily needed, it would look look not as pretty (normal foldout arrays without drag and drop functionality). I would need to do rewriting in order to remove my quality assurance logic and some documentation. Anyways, just PM me with your thoughts :)
     
  15. SpaceRay

    SpaceRay

    Joined:
    Feb 26, 2014
    Posts:
    455
    Now the "start conversation" appears on your profile

    I have activated the allow conversations and is ready, I never removed it, do not know what happens, but it seems that it is not showing on my profile, but then I went to "conversation" and started a new conversation and searched for you, so I have sent a PM now
     
  16. gdbjohnson3

    gdbjohnson3

    Joined:
    Mar 11, 2018
    Posts:
    13
    @Johannski This is great and very helpful. I assume then that your platform specific classes are basically serializable POCO's with maybe some custom behaviours specific for the given platform?
     
  17. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Yep exactly. I wanted to stay a bit flexible on how to define which device setting is used (for windows you might want to take display resolution graphics card and cpu into account, on iOS the model name might be enough).
    I think using ScriptableObjects for the different devices might be even nicer, since other scripts can easily listen if a specific device is selected.
     
  18. Qurious_Media

    Qurious_Media

    Joined:
    Jan 7, 2017
    Posts:
    4


    Hi @Johannski ,
    Thanks for sharing the script.
    I imported your script into my project, but I am getting errors like, IQualitySetting, IosDeviceSettings, TvOsDeviceSettings, AndroidDeviceSettings, StandaloneDeviceSettings, QualitySetting, DeviceNameMapping. I agree that these all classes are related with Odin Inspector. But can you please share us the script that will accessible with Unity's standard Inspector.
     
  19. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hey there,
    Thanks for asking. Since you're not the first person to mistake that code as simple copy pastable I added a note there. This was just a snippet from my whole system. I didn't intend to provide my complete solution, but just a simple guidance for those who are interested in implementing something similar.
     
  20. Ophainim

    Ophainim

    Joined:
    Jan 3, 2013
    Posts:
    1
    Hey @Johannski,

    This is very cool! I've implemented something similar, but you have fields I don't. Specifically, what is reference resolution vs real resolution?

    I assume the drop down qualities bar is stuff to indicate special case code in your settings classes?

    As a new UI programmer, I appreciate your help!
     
  21. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hey there,

    The reference resolution is for the canvas scaler (this setting will be used in the canvas scaler. This is especially useful if your ui scales good in one direction but has problems in the other direction. Is solves for example the problem of this very thread. It is also a great way to avoid having huge icons on tablets by giving them a larger reference resolution.
    Yes the rest is for special adjustments (for example with the notch for the iPhoneX).
     
  22. Smooth637

    Smooth637

    Joined:
    Mar 31, 2018
    Posts:
    1
    @Johannski, Did you by any chance manage to create this asset, If so, I would really love to buy it
     
  23. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hi @Smooth637,

    no, sadly I haven't got the time. I do have a different suggestion however that I found recently:
    Using the Screen Match mode "Expand" will help you keeping the ui intact when having very narrow aspect ratios. This does solve quite a few problems.

    If you got a more complex problem, you can also send me a DM with the problem :)

    upload_2020-4-8_11-27-47.png
     
    akusep likes this.