Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Please advise on how we are supposed to use Constant Physical Size.

Discussion in 'UGUI & TextMesh Pro' started by Mikeysee, Nov 20, 2014.

  1. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    Hi,

    I know you guys have only recently changed the way canvas scaling works but the documentation on how to use Constant Physical Size is really sparse so I was hoping to get some answers here.

    I have a HUD for my game that has buttons that ideally I would like to stay the same physical size so no matter the device the buttons are still pressable. In the editor I have designed it to the size I like:

    2014-11-20_13-46-54.png

    Then I have attached a CanvasScaler component:

    upload_2014-11-20_13-52-21.png

    All is well and good, but when I run it on my iPhone 5, I get:

    2014-11-20 13.34.37.png

    This is clearly not right.

    Im thinking the problem is that I have designed my HUD using the 96 DPI in the CanvasScaler. The problem is there doesnt seem to be any way to simulate higher DPIs when designing so instead I set the Fallback Screen DPI to the DPI of my iPhone (324).

    We now in the editor it looks like it does on the phone:

    upload_2014-11-20_13-56-17.png

    Okay, so now if I scale my HUD down to that size bad things start happening:

    2014-11-20_13-57-46.png

    Note the shadow is still set to 1 but looks like it is much greater than 1. The same goes for things like the spacing on Horizontal and Vertical Layout Containers.

    So basically im not sure if the way i'm doing things is right, can some Unity staff please give me some guidance on the correct way to develop Constant Physical Size UI's.
     
    SamFernGamer4k and rakkarage like this.
  2. Deleted User

    Deleted User

    Guest

    I think Constant Physical size keeps it the same size on any resolution?

    I used Canvas Scaler and "Scale to Screen" and it works fine for me.
     
    SamFernGamer4k and rakkarage like this.
  3. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    Yes, but I want to keep the buttons the same physical size no matter the DPI or resolution of the device.

    What im looking for is some advice on the correct way to use it.
     
  4. alestane

    alestane

    Joined:
    Sep 26, 2014
    Posts:
    13
    If you want parts of your UI to scale and parts not to, you might need two separate canvases with two different Canvas Scaler components.
     
    Siggytron likes this.
  5. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    Thats not what im saying. I am saying, how do we use the Constant Physical Size when developing for multiple devices.

    I am currently using several different canvas' for different scaling scenarios. Popups for example must always fit on the screen so they have a ratio based scaling. These HUD items must always be pressable and thus they should be scaled with physical size.

    What im looking for is some guidance on how to use Constant Physical Size in the editor.
     
    drew55 and geddon like this.
  6. TheFuntastic

    TheFuntastic

    Joined:
    Feb 11, 2013
    Posts:
    17
    What Mikeysee is looking for should be quite straightforward, but I've also come up short trying to figure it out. Really would be awesome if unity could simulate DPI in the game window, because right now it's incredibly difficult trying to figure out resolution scaling issues.

    I solved the problem by creating my own scaling component. Essentially it's just scaling the canvas based on some math. Physical size (mm) = pixels / dpi * 25.4

    This should give you the clue that to keep physical size constant, you need to increase the number of pixels proportionally to an increase of dpi. So if your dpi is 2x ( eg 320 dpi vs 160 dpi) then your canvas scale factor needs to be set to 2. (Note you will need to swap in a high res sprite if you want to take full advantage of the higher pixel density).

    What gets really confusing is the fallback dpi settings on the canvas scaler. Because the editor doesn't actually have any concept of dpi, it just makes things in the editor weird really quick.
     
    MarcSpraragen and Siggytron like this.
  7. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
  8. forcepusher

    forcepusher

    Joined:
    Jun 25, 2012
    Posts:
    227
    I've ran into the same issue, but figured out that i'm doing it wrong.
    Just got to use the anchors right.
     
  9. geddon

    geddon

    Joined:
    Apr 3, 2015
    Posts:
    1
    I've just ran into this problem myself, would love to see if anything has come of Mikeysee's variant!
     
  10. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    If anyone still needs a constant DP canvas scaler, the snippet I put here might help:

    [EDIT: New link as of 12/21/2020]
    https://repos.malkyne.org/_admin/gists/1

    Just drop that on your canvas, instead of CanvasScaler, and it should do the job.

    You should just be able to just use DP sizes, and it will scale them appropriately. Also, I've got it correcting the scaling in the editor, so it should behave the way you expect.

    If you want other versions (e.g. Standalone) to more closely match the element sizes you see in the editor for mobile, just fiddle with the preprocessor directives at line 100.

    If you see any bugs or other problems, let me know!
     
    Last edited: Dec 21, 2020
  11. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    HI! I hope someone will see this.

    I pasted your script in my project but I don't really understand how it works.
    Although the physical size seems to be conserved, the scaling isn't like any of the original CanvasScaler's modes.
    My question is: which unit do you use? It doesn't seem to be any of the original ones (cm, mm, inches, etc.).
     
  12. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    Hi, MingJ!

    The reason my canvas scaler is called "DpCanvasScaler" is because it uses DPs, which is short for "device independent pixels." You can learn more about them here:

    https://en.wikipedia.org/wiki/Device_independent_pixel

    I am using the Android formula for calculating DPs in my canvas scaler. This should make it easy for people who are trying to make an app that satisfies Google's Material Design style guide (which uses DP for all units), and it should provide consistent element sizing on most mobile devices.
     
    MarcSpraragen and moji_kashani like this.
  13. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    Thanks for the explanation. This method seems to be the best way to have a constant physical UI size on mobile, but does it work as well on standalone PC/Mac or Web?
     
  14. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    That's a great question! It depends entirely on whether the platform correctly reports its Screen.dpi in Unity. The last time I checked, it does pretty well on mobile devices, but it's not so great on desktop/laptop machines. I provide a Fallback Screen Dpi value that you can use to provide a fallback DPI on devices that return a 0 from Screen.dpi.
     
  15. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    I've tested it on several Laptops and it didn't really work. I measured 20 to 25% difference from what I had on my desktop screen (it's smaller than it should be), which is more than what I get with Unity's CanvasScaler. I'm guessing Screen.dpi just doesn't return the right number, although I don't know why.
    It works perfectly on Android tablets though (but I've only tried on 2).
     
  16. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    Yeah, I wish I could give you a better solution for computers, but if Unity doesn't provide me with a DPI value, I have no way to guess what their physical pixel density is. :(
     
  17. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    I know, I hope they'll manage to fix it someday. Thanks for the help anyway, your script might be useful to me in the future.
     
  18. Fragmental

    Fragmental

    Joined:
    Jun 30, 2013
    Posts:
    61
    Hello, Malkyne. Thank you for this script!

    I'm having an issue, however.

    I've turned off my canvas scaler script and have your dp canvas scaler script on my canvas instead. Everything looks relatively the same in the editor, but when I send my apk to my android devices, the ui elements are sort of smaller and a little blurry around the edges. Kind of like if I set default sprite dpi to a smaller number like 50 or if I set reference pixels per unity higher, like 200. I've tested this on both a phone and tablet with the same results. Howeve, I have confirmed that ui elements are the same size on both devices, which is great.

    I have everything set to default reference pixels per unit set at 100, fallback screen dpi and default sprite dpi set to 96, and dynamic pixels per unit set to 1. I don't really fully understand what all these settings are or what I can do to fix this issue. Any help is greatly appreciated.

    Edit: I should mention that I'm using the UGUI's default sprits.
     
  19. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    Your solution worked a treat on my Android build. The Unity one seems to be a total bust, don't understand how they could get that so wrong, it's not rocket science. Especially compared with everything they get right.
    I assume you reported it to them as an issue?
     
  20. fwalker

    fwalker

    Joined:
    Feb 5, 2013
    Posts:
    255
    How are you guys testing this? On the actual devices only? Is there any other way? I know the iOS simulators do not return the correct DPI right?
     
  21. bradweiers

    bradweiers

    Joined:
    Nov 3, 2015
    Posts:
    59
    @Malkyne what's the 160 here on line 98?

    Code (CSharp):
    1. float targetDPI = 160;
     
  22. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    Oh, heh, this was originally some tinkering code, and if I'd intended it for mass use, I'd have never made that a magic number. So embarrassed! :oops:

    Here is a reference document that explains the origins of that number:
    https://material.io/design/layout/pixel-density.html#pixel-density

    Specifically:
     
  23. moji_kashani

    moji_kashani

    Joined:
    Mar 10, 2020
    Posts:
    2
    Loved it Thanks
     
  24. jeango

    jeango

    Joined:
    Dec 19, 2012
    Posts:
    109
    I'm currently working on my first mobile game and want to have constant pixel size for my UI.
    Is this problem still a thing in Unity 2019.4? I'm not currently able to test on an actual device but I rather know sooner than later if I'm going to have to use this DP hack
     
    Eater_Games likes this.
  25. MichaelRaabAsap

    MichaelRaabAsap

    Joined:
    Dec 19, 2018
    Posts:
    1
    Hi, can you please share the code for Unity DP constant canvas scaler again? Thx
     
  26. cihad_unity

    cihad_unity

    Joined:
    Dec 27, 2019
    Posts:
    35
  27. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    Goodness, sorry about that! Due to some bad hosting luck, I had to migrate that snippet twice, in a relatively short period of time. I fixed up the link above, and here it is again, just in case: https://repos.malkyne.org/_admin/gists/1
     
  28. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    @Malkyne Thank for the code, did you try it under 2021.1? seem that changing the DPI (Reference PPU or Default Sprite DPI) have no impact. I can see that the canvas scaler ReferencePPU change but visually there is no impact.
     
  29. Malkyne

    Malkyne

    Joined:
    Nov 18, 2009
    Posts:
    39
    Sorry you're having trouble with this, Morphus74! What platform are you using this on? Desktop doesn't really identify DPI properly, so it has never really worked the way I'd like, there. If you're on mobile and it's not working properly, however, please let me know, so I can investigate the issue.

    I'm not using this snippet actively on any project right now (I mostly made it for my own tinkering), but it's popular enough that I like to keep it current for everybody!
     
  30. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Will have a look again and will let you know, thank for getting back to me
     
  31. cihad_unity

    cihad_unity

    Joined:
    Dec 27, 2019
    Posts:
    35
    For posterity,
    The following code gives correct answer on iOS but I haven't tested for all devices. I'm still using the code original code here. We might not need to write native plugin if anyone tests and sees correct results.

    Code (CSharp):
    1. _scaleFactor = Mathf.RoundToInt(Screen.dpi / 160f); //iPhone SE: 2, iPhone X: 3, iPhone XR: 2
     
  32. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Ok, back to that topics, seem I'm back working on UI.
    If you use the DP scaler, do you see something on the unity game windows if you change resolution? For me it always stay the same