Forum rules - please read before posting.

Fit Unity UI into Forced Aspect Ratio

When you're using a forced aspect ratio, AC automatically fits legacy Unity GUI menus to the adjusted screen bounds. For Unity UI you can use this script:


To use it, create a Unity UI Canvas with a Panel that stretches over the entire screen (Rect Transform: Stretch in all directions, Left/Top/Right/Bottom all zero) and add the script to it. Then add the actual menu elements as children of this panel. 

Comments

  • Great solution!
  • @ChrisIceBox is this something that'll be a custom script or an addition to AC's future?
  • Chris - Please feel free to take whatever you want of the script to put into AC if you like.
  • edited May 2016
    Hi! Sound like cool stuff, but will this work on the Dialogue system's UGUIs, I mean when working in tandem with AC? or is there something else one needs to do for DS's GUIs to fit the screen properly in that case?

    PS: never mind... it's in the manual.
  • edited May 2016
    BTW, the Bolt Riley developer pointed out that FitUIToAspectRatio.cs didn't accommodate Canvas Scalers. I updated the script in the Dialogue System's Adventure Creator package. If you don't use the Dialogue System, change your Fit() method to:

    void Fit() {
      if (mainPanel == null) {
        Debug.LogError("Assign Main Panel", this);
        return;
      }
      var rect = AC.KickStarter.mainCamera.LimitMenuToAspect(new Rect(0, 0, Screen.width, Screen.height));
      var scale = (m_canvasScaler != null) ? m_canvasScaler.referenceResolution.x / Screen.width : 1;
      mainPanel.sizeDelta = new Vector2(scale * -2 * rect.x, scale * -2 * rect.y);
    }

  • edited June 2018
    I'm probably doing something wrong, but when I use this it just moves my UI to the start of left side of the new aspect ratio so that it overflows on the right side. What I want is for it to shrink or expand to fit the forced aspect ratio in all screen sizes.
  • Hi! Is your Canvas set to stretch in all directions? Are you using the Canvas Scaler fix above? This is over 2 years old. I honestly don't know if Chris has already implemented something like this or better into AC itself. If both of those things look OK and you're still stuck, let me know whether you're using the Dialogue System or not, and what your Canvas setup is like.
  • AC does now support Unity UI position-limiting under certain conditions.

    What's your Menu's Position type?  Without the script, have you checked Always fit within screen? and defined your RectTransform boundary?
  • Hi there!
    May I ask, using Position Type Manual (subtitles), with a Unity uGUI interface, with "always fit on screen" enabled and the rectTransform boundary properly set, When and how should I call Menu.SetCentre?

  • Just wondering,is it necessary to call SetCentre on each update? Is it expensive?
    What about calling it as soon as the display size changes, or when the UI gets shows, or, (in my case) whenever a new Subtitle appears/changes?

  • edited October 28

    SetCentre becomes more expensive if Always fit within screen? is checked, as it has to account for that. But if you're using Unity UI, you can bypass this and update the RectTransform component(s) directly too.

    If it's stationary, a simple call when it's turned on (via the OnMenuTurnOn event) should be enough:

    using UnityEngine;
    using AC;
    
    public class PositionMenuExample : MonoBehaviour
    {
    
        public Vector2 menuPosition;
    
        private void OnEnable ()
        {
            EventManager.OnMenuTurnOn += OnMenuTurnOn;
        }
    
        private void OnDisable ()
        {
            EventManager.OnMenuTurnOn -= OnMenuTurnOn;
        }
    
        private void OnMenuTurnOn (Menu menu, bool isInstant)
        {
            if (menu.title == "Subtitles")
            {
                menu.SetCentre (menuPosition);
            }
        }
    
    }
    
  • I'm not really sure about what to pass to menuPosition; I'm forcing a 2:1 aspect ratio and the menù is set to be fullscreen. Should I pass Vector2.zero?

  • I meant, "Stretch to fit". Inside that Stretch to fit transparent panel I usually build every other kind of UI.

  • edited October 29

    I'm not really sure about what to pass to menuPosition

    You haven't said where on screen you want to re-position the menu to, but the SetCentre function's parameter takes screen-space coordinates as a Vector2. Placing it in the centre of the screen would be a case of calling:

    menu.SetCentre (new Vector2 (Screen.width / 2f, Screen.height / 2f));
    
  • menu.SetCentre (new Vector2 (Screen.width / 2f, Screen.height / 2f));

    would this "stretch to fit the whole view (black bars excluded)" UI element take "forced aspect ratio" and aspect ratio in consideration?

    should I put this on the canvas root of the menu, or on the first rectTransfom inside it?

  • Those particular values would place the menu in the centre, so it wouldn't be affected by the side-borders. Passing the second parameter as true would cause the vector to be in a co-ordinate space relative to the border, however - see its entry in the Scripting Guide.

    UI menus are disabled when turned off, so the exact script above would be best placed on a separate GameObject entirely. You could, however, likely just call menu.SetCentre in the OnEnable function if placed on the Canvas root.

  • edited November 3

    Thanks!
    I actually slightly changed the above code to take 0-1 screen space coords into consideration.

    Yes, I already had a look at that page, still, I'd love to know:

    1. What's the better place to put the fix-MonoBehaviour in the UIprefab? in the root or on the rect that's about to be resized?
    2. Could you please add an official version of such Component along next version of AC?
    3. Does it make any difference putting the above code in the Update or LateUpdate Unity events?
    4. What about a menu.StretchToFit method that, instead of centering it, it moves all the Anchors appropriately and also centres it, so that it's easier to build the UI (I opened a feat.Req. for this)

    Here's the "generic" code I'm reusing for each UI Prefab in the game (because, yes, I have to put one on each of those, not sure if there's a way to "centralise" it making this setting game-wide or a flag to automatically handle each custom prefab UI appropriately)

    public class MenuForceRatio : MonoBehaviour
    {
        public string menuName;
        public Vector2 menuScreenSpacePosition;
        public bool useAspectRatio;
    
        protected AC.Menu cachedMenu;
    
        private void Update()
        {
            if (!cachedMenu)
                cachedMenu = AC.PlayerMenus.GetMenuWithName(menuName);
    
            if (cachedMenu)
                cachedMenu.SetCentre(new Vector2 (Screen.width * menuScreenSpacePosition.x, Screen.height * menuScreenSpacePosition.y), useAspectRatio);
        }
    }
    
  • What's the better place to put the fix-MonoBehaviour in the UIprefab? in the root or on the rect that's about to be resized?

    It should make no difference if the script does not refer to the UI directly.

    Could you please add an official version of such Component along next version of AC?

    Such a script would be better-placed in the AC wiki, as it is a demonstration on how to use the API to get what you want.

    Does it make any difference putting the above code in the Update or LateUpdate Unity events?

    As the function ultimately manipulates UI component values, this would be more of a question for Unity. I should think you'd be fine with both.

    What about a menu.StretchToFit method that, instead of centering it, it moves all the Anchors appropriately and also centres it, so that it's easier to build the UI (I opened a feat.Req. for this)

    I've replied to the thread.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.
Do NOT follow this link or you will be banned from the site!