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

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:

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

Then I have attached a CanvasScaler component:

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

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

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:

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

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

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.

2 Likes

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.

3 Likes

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.

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.

1 Like

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.

2 Likes

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.

2 Likes

Definitely less of an issue now we have access to the source.

https://bitbucket.org/Unity-Technologies/ui/src/ee188cc9dc2659e5404a912dd1344ade0855e6d0/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs?at=4.6

Im thinking of doing my own variant on the Constant Phsical Size mixed with the Scale With Screen Size.

4 Likes

I’ve ran into the same issue, but figured out that i’m doing it wrong.
Just got to use the anchors right.

I’ve just ran into this problem myself, would love to see if anything has come of Mikeysee’s variant!

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!

5 Likes

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.).

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.

2 Likes

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?

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.

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).

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. :frowning:

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.

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.

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?

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?