9
\$\begingroup\$

I'm trying to create a board with this requirements:

  • It SHALL be square.
  • It SHALL fit available width OR height.
  • It SHALL be centered in the canvas.
  • It MAY be wrapped into as many additional intermediate canvases as needed.

I am playing with anchors but I am not finding any combination to do that. The only solution I can think is script some kind of "OnResize" of the container and set the size of the board programmatically.

This is the original layout. (1) is the BoardCanvas. (2) is the Board.

Original Layout

I want that if the screen becomes taller, the square grows, but still is square:

enter image description here

Or reduces:

enter image description here

But, although those previous examples are snapping to the top and bottom edges, I also want that if the vertical space becomes taller than the available width, then the square limits its size depending on the left and right borders:

enter image description here

Q1: Is there a way to do this with the anchors/pivots? It's ok for me to create intermediate canvases in between the BoardCanvas and Board itself if that works.

Q2: If so, where should I position the anchors? Do I need intermediate objects?

Q3: If not, is scripting the solution? Is there any OnResize on the canvas to handle? I can't see any resizing event in the list, but maybe I dont know where to look for it. I feel that testing it at every frame seems a bit overkill, event driven seems better.

Thanks!

\$\endgroup\$
12
\$\begingroup\$

Finally I found a way to do it (tested in v5.0.0), in a way that:

  • Does not need code, or conditionals to check orientation.
  • Does not hack with scales and neither needs a reference resolution.

In the UI video tutorials, there is a big part missing, although well documented in the text-documentation: The "auto-layouts" system.

Auto-layouts are mechanisms made of "layouts" and "layout controllers". Layout controllers are components that one can attach to the UI Game Object. Controllers can resize Rect Transforms intelligently.

Certain controllers may resize the object where the component is applied to, whilst other controllers may resize the children of that object.

There a few built-in controllers. One of those is the Aspect Ratio Fitter.

First, I select my Board panel and I attach a new Aspect Ratio Fitter component:

enter image description here

The Aspect Ratio Fitter seems to aim to "maintain" the object's wanted aspect ratio. To do so, either the object can be set to "wrap" around a child object (while maintaning the aspect ratio), or either it can be set to expand and fit its container (while maintaining the aspect ratio).

I then select Fit In Parent option and I specify that I want a perfect square by setting the desired aspect ratio to 1:

enter image description here

enter image description here

This yields in a very similar layout than the one I wanted, but I didn't have to tell the board its dimensions. But still, it knows it must be square, as depicted:

enter image description here

If I shrink vertically or expand, the square follows the parent, while maintaining the aspect ratio:

enter image description here

enter image description here

Magically, when the change is donw by reducing the width, there is no script to attach and no property to change, as the "Aspect Ratio Fitter" does that for us automagically:

enter image description here

Finally, as I wanted a bit of margin there, I just place a container rect transform that acts as the spacer and move the Board from the BoardCanvas into the MarginCanvas:

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Ah, awesome, this looks like an excellent solution. Glad you found it, thanks for sharing! \$\endgroup\$ – Chris McFarland Mar 26 '15 at 20:07
3
\$\begingroup\$

This is possible, but with probably just a small line of code or two for defining whether or not the screen is landscape or portrait and changing a couple values.

On the Canvas, you need to make the Canvas Scaler's "Ui Scale Mode" be "Scale with Screen Size", and make "Screen Match Mode" be "Match Width or Height":

enter image description here

Assuming the default Reference Resolution of 800x600 is used, and assuming the screen's viewport is landscape (eg Screen.width is greater than Screen.height), the Match slider needs to be set all the way towards Height as 1.

You're then going to want an Image on the Canvas using the middle/center anchor preset. You also want the Image's Width and Height to match your Canvas Scaler's Reference Resolution's Y value.

enter image description here

You can then resize the camera's viewport and see that the image retains its shape while stretching its height to match the viewport's height:

enter image description here


If the screen is portrait -- and this is where you'll probably need to code to check and/or change as required -- you need to make the Scaler's Match value be 0, and change your Image's Height and Width to match the Reference Resolution's X value. (in the pictures below, the Image's Width and Height are both 800)


If you're trying to fit a smaller image inside, you can "scale" the image by adjusting its width and height against the Reference Resolution's X or Y value (depending on landscape or portrait). So for example, I made a blue square that uses half of the Reference Resolutions' X value (since the viewport is portrait), and it scales and shrinks nicely:

enter image description here

And further, if you wanted a checkerboard or something, each image's X and Y position and Height and Width can be based on a percentage of the Canvas Scaler's Resolution to do whatever you please:

enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks Chris for your highly detailed answer. Finally I found a solution that does not need any line of code to check orientation, and does not hack with the scales and does not use a reference resolution. I'm going to post my own answer but I did'nt want to pass along without thanking your effort and illustration. \$\endgroup\$ – Xavi Montero Mar 26 '15 at 13:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.