Search Unity

CanvasHelper resizes a RectTransform to iPhone X's safe area

Discussion in 'iOS and tvOS' started by _Adriaan, Mar 9, 2018.

  1. drorriov

    drorriov

    Joined:
    Jun 7, 2014
    Posts:
    43
    Thanks.

    With Android you can set Player -> Resolution and Presentation -> Render outside the safe area (to false) and from virtual tests I did it seems it automatically place blank link beside the notch. Unless i missed something here..

    Thanks for the video, that would be great in the next unity release!
     
  2. Martin_Gonzalez

    Martin_Gonzalez

    Joined:
    Mar 25, 2012
    Posts:
    361
    What about doing it as a Unity package with a github url?

    Another question, is it necessary to have it in the Update, beside the orientation checks?
     
    Last edited: Dec 6, 2019
  3. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    If you want the safe area rect to update when you change your phone's orientation, yes. 'Back in the day', it was also possible that SafeArea didn't return a correct safe area on startup, so that required it to be in Update() as well.

    Regardless, removing this Update() is such a small optimisation that you really shouldn't bother.
     
  4. KevinBunn

    KevinBunn

    Joined:
    Oct 4, 2019
    Posts:
    1
    Just wanted to post and say thanks! Saved me a lot of time.
     
    _Adriaan likes this.
  5. OldKing_Wang

    OldKing_Wang

    Joined:
    Jan 25, 2015
    Posts:
    46
    thanks @_Adriaan code. :)

    here is my simplify version:

    just attach it to any RectTransform node.

    Code (CSharp):
    1.  
    2. public class FitRectTransformToSafeArea : MonoBehaviour
    3.     {
    4.         private void Awake() { DoRunLogic(); }
    5.  
    6.         public void ManualRun() { DoRunLogic(); }
    7.  
    8.         private void DoRunLogic()
    9.         {
    10.             var selfRectTransform = GetComponent<RectTransform>();
    11.             if (selfRectTransform == null)
    12.             {
    13.                 Debug.Log($"{name} no RectTransform attached");
    14.                 return;
    15.             }
    16.  
    17.             var rootCanvas = FindRootCanvas();
    18.             if (rootCanvas == null) return;
    19.  
    20.             var safeArea = Screen.safeArea;
    21.  
    22.             var anchorMin = safeArea.position;
    23.             var anchorMax = safeArea.position + safeArea.size;
    24.             anchorMin.x /= rootCanvas.pixelRect.width;
    25.             anchorMin.y /= rootCanvas.pixelRect.height;
    26.             anchorMax.x /= rootCanvas.pixelRect.width;
    27.             anchorMax.y /= rootCanvas.pixelRect.height;
    28.  
    29.             selfRectTransform.anchorMin = anchorMin;
    30.             selfRectTransform.anchorMax = anchorMax;
    31.         }
    32.  
    33.         private Canvas FindRootCanvas()
    34.         {
    35.             var nowTrans = transform.parent;
    36.             while (true)
    37.             {
    38.                 if (nowTrans == null)
    39.                 {
    40.                     Debug.LogError($"{name} no Canvas root found");
    41.                     return null;
    42.                 }
    43.  
    44.                 var canvas = nowTrans.GetComponent<Canvas>();
    45.                 if (canvas != null) return canvas;
    46.                 nowTrans = nowTrans.parent;
    47.             }
    48.         }
    49.     }
    50.  
     
  6. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    I updated the script in the original post today to include the check for ResolutionChanged() on mobile devices too. Your game will otherwise act weird on Chromebooks running Android apps and dual screen / foldable Android phones that can enable / disable parts of the screen.
     
    JustAnotherDude likes this.
  7. frank-ijsfontein

    frank-ijsfontein

    Joined:
    Sep 11, 2015
    Posts:
    16
    We had a nasty issue on iOS 13, where the canvas would not scale right on orientation changes. Finally fixed it by always calling
    SafeAreaChanged()
    in Update, and changing ApplySafeArea and SafeAreaChanged like below:

    Code (CSharp):
    1.  
    2.     private Rect lastPixelRect;
    3.  
    4.     void ApplySafeArea()
    5.     {
    6.         if (safeAreaTransform == null)
    7.             return;
    8.  
    9.         var safeArea = Screen.safeArea;
    10.  
    11.         Rect pixelRect = canvas.pixelRect;
    12.         if (pixelRect == lastPixelRect)
    13.             return;
    14.  
    15.         lastPixelRect = pixelRect;
    16.         Debug.Log($"{this}: Applying safe area with canvas size {pixelRect.size}", this);
    17.  
    18.         var anchorMin = safeArea.position;
    19.         var anchorMax = safeArea.position + safeArea.size;
    20.         anchorMin.x /= pixelRect.width;
    21.         anchorMin.y /= pixelRect.height;
    22.         anchorMax.x /= pixelRect.width;
    23.         anchorMax.y /= pixelRect.height;
    24.  
    25.         safeAreaTransform.anchorMin = anchorMin;
    26.         safeAreaTransform.anchorMax = anchorMax;
    27.         //...
    28.     }
    29.  
    30.     private static void SafeAreaChanged()
    31.     {
    32.          for (int i = 0; i < helpers.Count; i++)
    33.          {
    34.              helpers[i].ApplySafeArea();
    35.          }
    36.      }
    37.  
    It seems that the pixelrect of the canvas only changes a frame later than the safe area, and so it would update itself with wrong values. Checking the last pixelRect against the current one fixes it.
     
    Last edited: Apr 30, 2020
  8. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    This also sounds like a Unity issue! Please report this to them so we'll all see this fixed!
     
  9. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    I'm noticing that Screen.safeArea reports wrong values occasionally, when changing device orientation. Is anyone familiar with this iOS issue?
     
  10. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    Literally said this a few posts ago. If you want Unity to fix this, make a bug report!
     
  11. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    I updated the script again today, unifying
    onResolutionChanged
    and
    onOrientationChanged
    to
    OnResolutionOrOrientationChanged
    , as it conceptually makes more sense and fixed a small issue on some android devices that would report an orientation change but not a resolution change. I also removed some of the extra static functions such as
    GetCanvasSize()
    and
    GetSafeAreaSize()
    . If you still need those and a few more, here they are:

    Code (CSharp):
    1.     public static Vector2 GetCanvasSize()
    2.     {
    3.         return helpers[0].rectTransform.sizeDelta;
    4.     }
    5.  
    6.     public static Vector2 GetSafeAreaSize()
    7.     {
    8.         for (int i = 0; i < helpers.Count; i++)
    9.         {
    10.             if(helpers[i].safeAreaTransform != null)
    11.             {
    12.                 return helpers[i].safeAreaTransform.sizeDelta;
    13.             }
    14.         }
    15.      
    16.         return GetCanvasSize();
    17.     }
    18.  
    19.     public static Rect SafeAreaRect()
    20.     {
    21.         for (int i = 0; i < helpers.Count; i++)
    22.         {
    23.             if(helpers[i].safeAreaTransform != null)
    24.             {
    25.                 return helpers[i].safeAreaTransform.rect;
    26.             }
    27.         }
    28.      
    29.         return helpers[0].rectTransform.rect;
    30.     }
    31.  
    32.     public static float GetSafeAreaGap(Vector2 side)
    33.     {
    34.         Rect safeArea = Screen.safeArea;
    35.         Rect canvasRect = new Rect(0f, 0f, Screen.width, Screen.height);
    36.      
    37.         if(safeArea == canvasRect)
    38.             return 0f;
    39.          
    40.         float gap = 0f;
    41.          
    42.         if(side == Vector2.down)
    43.             gap = safeArea.y;
    44.         else if(side == Vector2.up)
    45.             gap = canvasRect.height - (safeArea.x + safeArea.height);
    46.         else if(side == Vector2.left)
    47.             gap = safeArea.x;
    48.         else if(side == Vector2.right)
    49.             gap = canvasRect.width - (safeArea.x + safeArea.width);
    50.          
    51.         return (gap / canvasRect.height) * helpers[0].rectTransform.sizeDelta.y;
    52.     }
     
  12. Arcalise

    Arcalise

    Joined:
    Sep 27, 2019
    Posts:
    20
    Probably super simple question but where does the code "ApplicationManager.isLandscape" come from?

    I'm using unity beta 2020 i cant find any info on ApplicationManager.
     
  13. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    Ahhh woops, that was leftover code from one of my own projects :) I removed those two lines from the script in the original post, and as should you!
     
  14. SlimeProphet

    SlimeProphet

    Joined:
    Sep 30, 2019
    Posts:
    50
    This does not seem to work in Device Simulator (preview, 2.2.2) for me. Should it?
     
  15. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    It works for me as expected, but only in play mode. It does seem that the Device Simulator only applies the safe area when in play mode?
     
    SlimeProphet likes this.
  16. SlimeProphet

    SlimeProphet

    Joined:
    Sep 30, 2019
    Posts:
    50
    Thanks for letting me know. I was trying to set the position of something at runtime, and it was going to the wrong place. Must be a problem in my code. I'm still learning UGUI. I'll take another look.
     
  17. xaldin-76

    xaldin-76

    Joined:
    Oct 1, 2016
    Posts:
    25
    This works like a charm! And previews correctly in the device simulator. Thank you a lot for this, I think you should sell it on the asset store haha

    To make it always working (not just while in play mode) simply add [ExecuteAlways] in the script, like here https://docs.unity3d.com/ScriptReference/ExecuteAlways.html
     
    Last edited: Jun 12, 2020
    shacharoz likes this.
  18. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    I played around with this idea but it would require some more changes to the script that would make it more complicated... I don't know. One example: you don't want to call those resize functions in-editor.
     
  19. xaldin-76

    xaldin-76

    Joined:
    Oct 1, 2016
    Posts:
    25
    Honestly it's working perfectly here. No console exceptions or anything, is there something that i'm not seeing?

    Edit: Never mind, it sometimes gave lots of exceptions (only in the editor)



     
    Last edited: Jun 14, 2020
  20. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    Awake() is only called once after creating an object, and the domain gets reloaded after a script compilation, so you'd lose access to the CanvasHelper singleton and because of that Update() will no longer work and any other scripts with ExecuteAlways dependent on the CanvasHelper would go bust. We'd need to rewrite the script to accomodate OnEnable and OnDisable instead of Awake and OnDestroy, and all the static functions would need more checks. This is all trivial work but like I said: it complicates the script, and I prefer an understandable and minimal script over a large complicated one!
     
    Last edited: Jun 15, 2020
  21. xaldin-76

    xaldin-76

    Joined:
    Oct 1, 2016
    Posts:
    25
    Ah yes I got it now, thanks for explaining that was helpful. Using the script in playmode is just enough anyway.
     
  22. abhayr

    abhayr

    Joined:
    Jan 31, 2017
    Posts:
    1
    Thanks brother. this works like charm. I was looking for a solution for iPhoneX and you saved a lot of my time!

    However, we also have an implementation to change the orientation on some screens (one rest of the app we don't allow auto-rotation). so, if we go to landscape automatic on that screen but came to other without automatic change to portray rather by the code then the Unity doesn't change the safeArea correctly and canvas helper sill using landscape safe-area.
    To fix this, we have saved the safe-area on each orientation change for each orientation and instaed of using Screen.safeArea, we use save safeArea for the current orientation (if already saved). This is working fine for us.

    Let me know if you found any potential issue in it. Attached are some changed snippet:

    private void updateSafeAreaForOrientation()
    {
    if (!_safeAreas.ContainsKey(Screen.orientation))
    {
    _safeAreas.Add(Screen.orientation, Screen.safeArea);
    }
    }

    void Update()
    {
    if (disableSafeScreenDrawing)
    return;

    if (helpers[0] != this)
    return;

    if (Application.isMobilePlatform && Screen.orientation != lastOrientation)
    {
    updateSafeAreaForOrientation();
    OrientationChanged();
    didOrientationChangedOnce = true;
    if(_safeAreas[Screen.orientation] != lastSafeArea)
    {
    ForceUpdateSafeArea(_safeAreas[Screen.orientation]);
    }
    }

    if (!didOrientationChangedOnce && Screen.safeArea != lastSafeArea)
    {//updating safe area here till orientation changed happens.
    SafeAreaChanged();
    }
    if (Screen.width != lastResolution.x || Screen.height != lastResolution.y)
    ResolutionChanged();
    }

    private static void ForceUpdateSafeArea(Rect safeArea)
    {

    lastSafeArea = safeArea;

    for (int i = 0; i < helpers.Count; i++)
    {
    helpers.ApplySafeArea();
    }
    }
     
  23. Hoorza

    Hoorza

    Joined:
    May 8, 2016
    Posts:
    45
    You, Sir, are a gentleman and a scholar! Thank you very much!
     
  24. Hoorza

    Hoorza

    Joined:
    May 8, 2016
    Posts:
    45
    Make sure you actually name Child object for your Canvas "SafeArea" not "Safe Area" or you will spend 4 hours trying to make work with no luck...
     
    andrew_pearce_ and _Adriaan like this.
  25. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    169
    Thanks for the tip _Adriaan ! I personally do not want to risk (less changes = less issues with git) and instead changed the viewport of the camera =) The iOS users are minority in my case + plus notched phones are minority from that minority. I believe they will be happy with black line on the top and the bottom. Someone asked for this solution too in the topic and pushed me to this solution:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [RequireComponent(typeof(Camera))]
    4. public class CameraNotchSupport : MonoBehaviour {
    5.  
    6. #if UNITY_IOS
    7.   private Rect lastSafeArea = Rect.zero;
    8.   private Rect safeArea = Rect.zero;
    9.   private Camera camera;
    10.  
    11.   private void Start() {
    12.     this.camera = this.GetComponent<Camera>();
    13.   }
    14.  
    15.   void Update() {
    16.     this.safeArea = Screen.safeArea;
    17. #if UNITY_EDITOR
    18.     // simulate iPhoneX inside editor https://assetstore.unity.com/packages/tools/gui/safe-area-helper-130488
    19.     this.safeArea = (Screen.height > Screen.width) ? new Rect(0f, 102f / 2436f * Screen.height, 1f * Screen.width, 2202f / 2436f * Screen.height) :  // Portrait
    20.       new Rect(132f / 2436f * Screen.width, 63f / 1125f * Screen.height, 2172f / 2436f * Screen.width, 1062f / 1125f * Screen.height); // Landscape
    21. #endif
    22.  
    23.     if (this.safeArea != this.lastSafeArea) {
    24.       this.lastSafeArea = this.safeArea;
    25.  
    26.       this.safeArea.x /= Screen.width;
    27.       this.safeArea.width /= Screen.width;
    28.       this.safeArea.y /= Screen.height;
    29.       this.safeArea.height /= Screen.height;
    30.       this.camera.rect = this.safeArea;
    31.     }
    32.   }
    33. #endif
    34. }
    I do not have notched iPhone so I will test it with emulator and update my post. If anyone can test it with real phone, that will help a lot. Thanks

    UPD: Works fine on emulator, I had to modify code a bit =)
     
    Last edited: Feb 9, 2021
  26. Nokola

    Nokola

    Joined:
    Jul 25, 2015
    Posts:
    5
    Thank you for this! Worked immediately by following the instructions in the first post and using Unity 2020.3.1f1 LTS.
     
  27. SiWoC

    SiWoC

    Joined:
    Feb 16, 2021
    Posts:
    9
    Great, works like a charm indeed.

    Question, when my build is mobile only, portrait only, I can remove all the xxxChanged stuff right?
    So I end up with only 1 call to ApplySafeArea in Awake.
     
  28. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    No. The Safe Area may be reported by the OS after the first Awake after opening your app. Like I said in an earlier comment to someone here: removing the update from this script is such a small optimisation that you shouldn't bother. There are edge cases where the safe area changes. Just leave it there.
     
  29. Lumpazy

    Lumpazy

    Joined:
    Apr 24, 2018
    Posts:
    45
    Kudos ! Thanks
     
  30. NeverForgetRay

    NeverForgetRay

    Joined:
    Oct 16, 2021
    Posts:
    1
    I have submitted the Unity bug about the pixelRect dimensions lagging a frame behind the safeArea being updated (that a few people mentioned previously). I ran into it as well in Unity 2020.3.

    I was seeing this behavior in the simulator.

    Unity's team has reproduced it. There is an active ticket on it. They note that it is indeed broken in the simulator, but it works fine on device (pixelRects and safeAreas are synchronized on actual devices).
     
  31. aromana

    aromana

    Joined:
    Nov 11, 2018
    Posts:
    137
    Can you share a link to the bug?
     
  32. shacharoz

    shacharoz

    Joined:
    Jul 11, 2013
    Posts:
    98

    hi all,
    any ideas why this doesn't work when I rotate the screen with the device simulator or when changing the device itself?
    the first time works like a charm, but from that point on I receive wrong resluts.
    I'm using unity 2020.3.25
     

    Attached Files:

    • 1.png
      1.png
      File size:
      85.5 KB
      Views:
      276
    Last edited: Feb 6, 2022
  33. shacharoz

    shacharoz

    Joined:
    Jul 11, 2013
    Posts:
    98
    this is cool, didn't know about this, thanks!

    p.s. weirdly, now the script works as expected inside the editor, but when I go to play mode, it still shows the screenshots I present above.
     
  34. shacharoz

    shacharoz

    Joined:
    Jul 11, 2013
    Posts:
    98
    on the build on the phone, it works.
    after I put [executealways] on the script, it works awesome when editor.
    but not in play mode.
     
  35. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    The script wasn't built for use in the device simulator per sé. As mentioned in an earlier post in this thread, adding [ExecuteAlways] has some caveats that would make this script more complicated (#70), and I decided not to apply those changes to the script I posted. That shouldn't stop you from making those changes yourself, but that's up to you ;)
     
  36. shacharoz

    shacharoz

    Joined:
    Jul 11, 2013
    Posts:
    98
    hi adriaan.
    but I cant see it in play mode also...
    i mean, should I just trust you that it would work?
    i did try on my phone, and it worked very well.
    so do you think that it would work the same on all phones?
     
  37. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    Don't trust anyone on the internet, ever ;) I used the code I shared for Hidden Folks, which runs without issues on millions of iOS and Android devices. All my script really does is take Unity's Screen.safeArea and apply it to a RectTransform, so as long as Unity's Screen.safeArea reports correct values and you designed your UI to adhere to that SafeArea RectTransform, you should be fine.
     
  38. dynamicbutter

    dynamicbutter

    Joined:
    Jun 11, 2021
    Posts:
    63
    Thanks! Your code works for me and saved me some time.
     
  39. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,269
    This is a great idea - I don't understand why Android has 1-click support built-in for safe area support and iOS you have to roll your own though?! Maybe some Android API supported thing
    This should of course be a part of the Unity API already...
     
  40. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    As far as I understand it, on Android, you can toggle rendering outside of the safe area entirely. I wouldn't consider that 'safe area support'; just a lazy and ugly way to 'support' safe areas, because your game wouldn't cover the entire screen while nearly all other apps would. It makes your app feel outdated... which it would essentially be ;)
     
    andyz likes this.
  41. tobias_unity

    tobias_unity

    Joined:
    Feb 3, 2018
    Posts:
    66
    Hey @_Adriaan, the script has disabled the buttons in my canvas. Even after removing the script they still don't work. Any idea why? I'm using 2021.2.17f1
     
  42. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    My script doesn't disable any objects, so something else must have disabled your buttons. So... totally off-topic: I bet that you put a raycast target 'on top of' your UI or buttons, like a full screen image or something, making it so that the input event system never reaches your buttons. Look for Image components in your UI and uncheck 'raycast target' for everything that shouldn't receive input.
     
  43. tobias_unity

    tobias_unity

    Joined:
    Feb 3, 2018
    Posts:
    66
    Yes, I did and you are totally correct, sir. Thanks!
     
  44. kennyrogersjr

    kennyrogersjr

    Joined:
    Dec 26, 2022
    Posts:
    1
    @_Adriaan I've been wanting to write a similar script for a couple days and stumbled across a fan that mentioned your code/post. I figured nobody probably kept it cleaned up, but you did. Thank you for writing and sharing this! Great idea and phenomenal upkeep; you've really whittled it down over the years, too.

    Friendly feedback, I noticed that this version has an unused var (most likely from a major rewrite):
    Code (CSharp):
    1. private RectTransform rectTransform;
    and:
    Code (CSharp):
    1. rectTransform = GetComponent<RectTransform>();
    Also, not sure if this is a me-ism or what, but setting the following to its current value seems like extra script work on instantiation (not really) and uses a deprecated command instead of just setting it to 0.
    Code (CSharp):
    1. private static ScreenOrientation lastOrientation = ScreenOrientation.Unknown;
    2. private static ScreenOrientation lastOrientation = 0;
    Looking at the UnityEngine.CoreModule, ScreenOrientation attributes Unknown to 0, so not a crazy deprecation.

    Hope this helps! Again, thank you so much!
     
  45. Amitloaf

    Amitloaf

    Joined:
    Jan 30, 2012
    Posts:
    97
    So... It's not working for me. I mean, it does work, but the sizes are completely wrong. Just letting you know. Will try to figure out why that happens.
    upload_2023-1-4_13-50-56.png upload_2023-1-4_13-51-16.png
     
  46. WayneVenter

    WayneVenter

    Joined:
    May 8, 2019
    Posts:
    56
    This stopped working in Unity 2022.3.0f1 LTS, still works in Unity 2021.3.26f1
     
  47. Tinsa

    Tinsa

    Joined:
    Jul 24, 2018
    Posts:
    3
    I am using this in 2022.3.4f1, but I am not sure what is causing the problems I have yet.

    Whenever I restart the Unity editor, my y positions of the game objects on the panels are reset to 0 which makes everything move around. It does not matter if the objects are anchored to the top or the bottom, the y position is lost when restarting the editor. When anchored to the center, the position is saved between editor restarts...

    Has anyone else seen this when using the CanvasHelper script or is this something else in my project? (I did not notice this before starting to use this script and I have been working in this project for 1-2 years now. I did update from Unity 2021 to 2022 recently as well...)
     
  48. mikehk

    mikehk

    Joined:
    Jun 13, 2023
    Posts:
    1

    Based on @_Adriaan's update, I simplified it for those who are enabling & disabling UIs with a Canvas on them (for UI performance improvement) for their scenarios.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. // Source: https://forum.unity.com/threads/canvashelper-resizes-a-recttransform-to-iphone-xs-safe-area.521107
    4. /// for notch devices
    5. [RequireComponent(typeof(Canvas))]
    6. public class CanvasHelperCustom : MonoBehaviour
    7. {
    8.     private bool screenChangeVarsInitialized = false;
    9.     private ScreenOrientation lastOrientation = ScreenOrientation.LandscapeLeft;
    10.     private Vector2 lastResolution = Vector2.zero;
    11.     private Rect lastSafeArea = Rect.zero;
    12.  
    13.     private Canvas canvas;
    14.     [SerializeField] private RectTransform safeAreaToTransform;
    15.  
    16. #if !UNITY_EDITOR
    17.     private void Awake()
    18.     {
    19.         canvas = GetComponent<Canvas>();
    20.     }
    21.  
    22.     private void OnEnable()
    23.     {
    24.         if (!screenChangeVarsInitialized)
    25.         {
    26.             lastOrientation = Screen.orientation;
    27.             lastResolution.x = Screen.width;
    28.             lastResolution.y = Screen.height;
    29.             lastSafeArea = Screen.safeArea;
    30.  
    31.             screenChangeVarsInitialized = true;
    32.         }
    33.  
    34.         ApplySafeArea();
    35.     }
    36.  
    37.     private void Update()
    38.     {
    39.         if (Application.isMobilePlatform && Screen.orientation != lastOrientation)
    40.             OrientationChanged();
    41.  
    42.         if (Screen.safeArea != lastSafeArea)
    43.             SafeAreaChanged();
    44.  
    45.         if (Screen.width != lastResolution.x || Screen.height != lastResolution.y)
    46.             ResolutionChanged();
    47.     }
    48.  
    49.     private void ApplySafeArea()
    50.     {
    51.         if (safeAreaToTransform == null)
    52.             return;
    53.  
    54.         var safeArea = Screen.safeArea;
    55.  
    56.         var anchorMin = safeArea.position;
    57.         var anchorMax = safeArea.position + safeArea.size;
    58.         anchorMin.x /= canvas.pixelRect.width;
    59.         anchorMin.y /= canvas.pixelRect.height;
    60.         anchorMax.x /= canvas.pixelRect.width;
    61.         anchorMax.y /= canvas.pixelRect.height;
    62.  
    63.         safeAreaToTransform.anchorMin = anchorMin;
    64.         safeAreaToTransform.anchorMax = anchorMax;
    65.     }
    66.  
    67.     private void OrientationChanged()
    68.     {
    69.         //Debug.Log("Orientation changed from " + lastOrientation + " to " + Screen.orientation + " at " + Time.time);
    70.  
    71.         lastOrientation = Screen.orientation;
    72.         lastResolution.x = Screen.width;
    73.         lastResolution.y = Screen.height;
    74.     }
    75.  
    76.     private void ResolutionChanged()
    77.     {
    78.         //Debug.Log("Resolution changed from " + lastResolution + " to (" + Screen.width + ", " + Screen.height + ") at " + Time.time);
    79.  
    80.         lastResolution.x = Screen.width;
    81.         lastResolution.y = Screen.height;
    82.     }
    83.  
    84.     private void SafeAreaChanged()
    85.     {
    86.         // Debug.Log("Safe Area changed from " + lastSafeArea + " to " + Screen.safeArea.size + " at " + Time.time);
    87.  
    88.         lastSafeArea = Screen.safeArea;
    89.  
    90.         ApplySafeArea();
    91.     }
    92.  
    93.     [ContextMenu("Apply Safe Area Change")]
    94.     private void ApplySafeAreaChange()
    95.     {
    96.         ApplySafeArea();
    97.     }
    98.  
    99. #endif
    100. }
     
    Last edited: Feb 6, 2024