Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How can I make a thin frame that works in every resolution?

Discussion in 'UGUI & TextMesh Pro' started by robal1991, Mar 20, 2019.

  1. robal1991

    robal1991

    Joined:
    Mar 31, 2016
    Posts:
    33
    Hello I have a problem with making thin frame that will be thin on every resolution.
    My current setup is fine as long as the resolution is high enough - 1920x1080 or higher.
    It looks like this:
    upload_2019-3-20_10-5-31.png
    But when I lower the resolution to 1366x768 sometimes some edges disappear...
    upload_2019-3-20_10-6-23.png or upload_2019-3-20_10-7-27.png

    My app has to work also on 4k but it works fine all the time.

    Currently I have grey image with no sprite
    upload_2019-3-20_10-12-48.png
    and on top of it I have another image with no sprite with white color with margins Left=1, Right=1, Top=1, Bottom=1.
    upload_2019-3-20_10-11-36.png

    Previously I've had a texture with a frame but there was problem with the approach too - on higher resolutions frame was too thick.

    My canvas settings are:
    Screen Space - overlay
    scale with screen size
    ref resolution 1920x1080
    screen match mode - shrink

    After some research I tried to simplify the problem: I cannot make a thin, vertical line (width=1) to be correctly rendered on small resolutions. The line just disappears.

    Can you guys help how can I fix this?
    Thanks.
    Michael
     
    Last edited: Mar 20, 2019
  2. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    Use "sliced" mode sprites, that's what they're for.
     
  3. robal1991

    robal1991

    Joined:
    Mar 31, 2016
    Posts:
    33
    Ofc I tried it and it doesn't work neither... :( I tried different sizes of the texture :(
    upload_2019-3-21_9-28-13.png

    If i change the inputfield width from 50.0 to 50.1 the edge sometimes appear. How can I assure that all edges will be drawn?


    Some time ago my canvas scaler settings were different - reference resolution was 1366x768 and I didnt have this problem back then, but on full hd resolution everything was too thick and it looks like a technology from 20 years ago. So I changed reference resolution to 1920x1080... but now on smaller resolutions 1px lines disappear...


    One thing I could do is to increase frame thickness from 1px let's say to 1.5px depending on how much smaller current canvas size is. Will it work?
     
    Last edited: Mar 21, 2019
  4. robal91

    robal91

    Joined:
    Sep 24, 2019
    Posts:
    3
    I attach a zip with example project of my problem.
    There are 2 frames on the scene created with 2 different approaches. You can change canvas reference resolutions with Z an X keys.
    My goal is to preserve correct frame rendering at least at 1366x768 resolution.
     

    Attached Files:

    Last edited: Sep 26, 2019
  5. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    I haven't downloaded your project, but my guess is that you have a Canvas Scaler attached to your Canvas, which is resizing absolutely everything in your UI based on the current screen resolution. If the resolution gets small enough, this applies a scaling value that makes your line less than 1 pixel tall, at which point rounding issues might cause it to disappear.

    You could possibly write a script that would invert the effect of the canvas scaler for just this one element, but if your whole UI is scaling depending on resolution then it would probably make more sense just to choose a size that will be 1 pixel at low resolution and more than one pixel at higher resolution, so that it's always a consistent percentage of the screen size.
     
  6. robal91

    robal91

    Joined:
    Sep 24, 2019
    Posts:
    3
    Yes, im using canvas scaler in "scale with screen size" mode (because I want frame width and frame height to be scaled), but I want the frame thickness to actually be "constant pixel size"...

    1px thickness at lower resolution is causing the problem, that on 4k (which my application has to support) the frame is too thick and it looks bad. I've tried that already....
     
  7. robal91

    robal91

    Joined:
    Sep 24, 2019
    Posts:
    3
    I've written a script that thickens the line if screen is smaller than my reference scaling resolution. Line is always rendered, but sometimes I'm getting now a opposite problem. Because of rounding my line is sometimes rendered with 2px thickness. Can someone give me a link where the actual canvas rendering mechanism is explained? I would like to be able to calculate final and actual line thickness on screen.

    I'm getting 2px line for example for 1500x800 screen size. In this case left and right frame edges have 1.28 thickness, and top/bottom have 1.35. Up to 1507x800 its incorrect, but 1508x800 is ok up to 1619x800. 1620x800 is incorrect again...

    upload_2019-9-28_22-38-2.png

    I attach my current test project.

    Additional info: My frame size is 128x32. My application is in WebGL and browser window is resizable. Bellow 1280x720 frame can disappear (the lowest supported resolution is taken from stats gathered by our client).

    Thanks for help! :)
     

    Attached Files:

    Last edited: Sep 28, 2019
  8. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    The Canvas Scaler works by applying a scale value to the Canvas object, which is then inherited by everything below it.

    Transform.lossyScale will tell you an object's "global" scale, taking into account the scale factors of all its ancestors, including the scaled Canvas. So you can force an object to a global scale of S with something like:

    Code (CSharp):
    1. transform.localScale = new Vector3(
    2.     S.x * transform.localScale.x / transform.lossyScale.x,
    3.     S.y * transform.localScale.y / transform.lossyScale.y,
    4.     S.z * transform.localScale.z / transform.lossyScale.z
    5. );