1
\$\begingroup\$

I have a TextMeshPro GameObject, which I placed within the Canvas. The canvas is set to Scale with Screen Size and has a reference resolution of 1440x1080.

The TextMeshPro GameObject is anchored to the top-right and its position horizontally is -185 from the anchored point (top-right). And within 1440x1080 resolution it looks like:

enter image description here

But when I make my Display resolution higher or smaller (like for example 1920x1080 as in the image below), the TextMeshPro GameObject goes outside game and ends up in the black area.

enter image description here

I tried changing the position of TextMeshPro GameObject via a script attached to the canvas. I came up with the following formula but it seems wrong.

DisplayResolution.x - (DisplayResolution.X + (ReferenceResolution.X - TextMeshPro.Location.X))

Assuming:

DisplayResolution.X = 1920
ReferenceResolution.X = 1440
TextMeshPro.Location.X = -185

Edit - answer to comments:

Where Starry Backfield is at:

enter image description here

Camera settings:

enter image description here

Canvas Settings:

enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ How is your starfield backdrop drawn at present? Is it intended to not fill the horizontal extents of your window? \$\endgroup\$
    – DMGregory
    May 9, 2020 at 11:38
  • \$\begingroup\$ @DMGregory It's presented with the camera, the camera uses 4:3 aspect ratio. The camera Size is set to 12 and it has a Transform.Position of x=12 and y=9. However, the Reference resolution of the Canvas is set to 1440x1080 which also is 4:3. I updated the question and added an image with an arrow where the starfield backdrop is drawn. \$\endgroup\$
    – sdfsd
    May 9, 2020 at 11:48
  • \$\begingroup\$ @DMGregory I updated the question and added screenshots of my Camera and Canvas settings. It's set to work with world units. \$\endgroup\$
    – sdfsd
    May 9, 2020 at 12:03

1 Answer 1

1
\$\begingroup\$

Ah, the joy of creating resolution-responsive screen layouts in Unity.

If I understand you correctly, your goal is to create an UI which always preserves its aspect ratio, but also fills as much of the screen as possible, letterboxing or pillarboxing as necessary.

If that is the case:

  1. If your canvas itself has a Canvas Scaler component, remove it.
  2. Add a new empty game object to the canvas (let's call it "Content").
  3. Set the anchor preset in the "Content" to "Stretch" in both directions
  4. Resize the "Content" to fill the whole canvas.
  5. Add an "Aspect Ratio Fitter" to "Content". Set its Aspect Mode to "Fit In Parent" and its "Aspect Ratio" to the ratio of width to height you want it to maintain.
  6. Add your UI elements as children of "Content". Make sure their anchors are the corners you want them to stay relative to. For example, if you want your score text to always stay in the upper right corner, set its anchor to upper right and drag it into the upper right corner.
  7. [optional] Do you want the elements in "Content" themselves to shrink or enlarge with different screen sizes so they don't overlap on low resolutions and don't become too small on large resolutions? Then add a "Canvas Scaler" to "Content". Set its UI Scale Mode to "Scale With Screen Size" and its Screen Match Mode to "Expand".

Your UI should now behave as described.

Now the next challenge would be to get the rendering of the actual game to behave the same way as the canvas and letterbox/pillarbox as the resolution requires. But that's outside of the scope of this question.

4:3 aspect ratio:

4:3

Landscape aspect ratio:

Landscape

Portrait aspect ratio:

Portrait

\$\endgroup\$
3
  • \$\begingroup\$ your solution seem to work, however I wanted to confirm that with empty node you mean empty Game Object? The optional step where I add the Canvas Scaler component to Content, it's not letting me, it tells me: Non-root Canvasses will not be scaled. \$\endgroup\$
    – sdfsd
    May 9, 2020 at 12:46
  • \$\begingroup\$ @OS To be precise, what I mean is to right-click on the canvas in the Hierarchy tree, and click on "Create Empty". The result should be a new GameObject as a child of the canvas with a RectTransform component and nothing else. I have never seen a use-case for nesting multiple canvases within each other. \$\endgroup\$
    – Philipp
    May 9, 2020 at 12:50
  • \$\begingroup\$ Thank you for the answer! Your solution is amazing! There only one little error I found, the ` CanvasScaler ` from the Canvas shouldn't be removed. The only thing that needs to be done is setting itsScreen Match Mode to expand, so that you can remove the optional step. \$\endgroup\$
    – sdfsd
    May 9, 2020 at 12:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .