#Unity UI: Why does viewport.rect.width change so drastically between resolutions?

1 messages · Page 1 of 1 (latest)

simple holly
#

TLDR After initial message.

I'm building a dynamic inventory system where text items are placed in rows, creating a new row when items don't fit. I'm facing a strange issue with viewport width calculations.


The Problem
I need to determine the available width to decide when to create a new row. However, the viewport.rect.width values I'm getting are drastically different between resolutions:

In 1440x2960: viewport.rect.width = 1481.03
In 2960x1440: viewport.rect.width = 6125.474

This is causing layout issues where:

Items overflow in 1440x2960
Items don't fill the space efficiently in 2960x1440

What I've Tried
Using TextMeshPro's preferredWidth:

float itemWidth = itemNameTMP.preferredWidth;

Using LayoutElement's preferredWidth:

float itemWidth = item.GetComponent<LayoutElement>().preferredWidth;

Using Reference Resolution:

float usableWidth = canvasScaler.referenceResolution.x;

Using Viewport Width with Safety Margin:

float usableWidth = viewport.rect.width * 0.95f;

Using Different Safety Margins Based on Resolution:

float safetyMargin = (Screen.width > Screen.height) ? 1.0f : 0.75f; float usableWidth = viewport.rect.width * safetyMargin;

None of these approaches work consistently across both resolutions.

My Canvas Setup
Canvas Scaler UI Scale Mode: ScaleWithScreenSize
Reference Resolution: (1440, 2960)
Screen Match Mode: MatchWidthOrHeight
Match value: 1 (match height)

The Question
Why is viewport.rect.width so much larger (6125) in 2960x1440 compared to 1440x2960 (1481)?

What's the proper way to calculate available width for UI elements that works consistently across all resolutions?

#

'

TLDR:

I have **Rows ** object that has a Vertical Layout Group.

And within it, I want to dynamically add Row objects with a Horizontal Layout Group

I'm trying to figure out how many can I add before overflowing. If I detect an overflow, I'm trying to create a new Row object and attach IntentoryItemUI objects until it overflows. Rinse and repeat.

#

Here you can see that despite my best efforts, some objects still overflow from the viewport.

minor zealot
#

I think relying on a rect transform width as a measure of screen size is gonna be super unreliable.if it is resized automatically(with a size fitter or something), it could have all kinds of arbitrary values.
Maybe use a grid layout group instead and modify the viewport size manually or let the user do it as they please.

simple holly
#

@minor zealot Thanks for the response. It is set to strectch in all directions, and yes very unreliable. Never really delt with grid but not sure if it'll be useful here since I still need to rely on the size information to fit just the right amount of items per row

minor zealot
simple holly
minor zealot
#

Is viewport variable of type RectTransform?

#

Did you try using some other RectTransform properties, like sizeDelta?

simple holly
#

@minor zealot Had to upload as file. I also tested the sizeDelta for every component but doesn't seem to be what I want

minor zealot
#

Upload !code properly:

storm epochBOT
minor zealot
#

sizeDelta should be the most reliable variable. If it doesn't match your expectations, there must be something weird with your setup.

#

Is it a screen space canvas?

#

Or maybe you have some objects in the hierarchy scaled weirdly?

#

Or perhaps you're debugging at some weird timing when the canvas is being rebuilt.

simple holly
#

Hmm, that might be it. I am adding things and am not waiting for the next frame.

#

On second thought, it shouldn't be the case. The viewport size (the inventory width) never changes. All I'm trying to do is to get its width, and fit as many items as it can take per row.

#

Item widths are dynamic but TextMeshProUGUI width seems to be reliable and doesn't need end of frame magic

#

When I enter magical numbers, after my calculations, like availableWidth * 0.75f, I can get it to perform perfectly on one resolution. But on a wider or narrower screen, it either leaves gaps or overflows

minor zealot
#

What's the scale of the viewport object and all it's parents? Are you modifying it via code at some point?

simple holly
#

Nope, all scales are default. Inventory and parents never change size on runtime

#

If you think @minor zealot that this approach makes sense and it should work, I will revisit my code and go step by step. I just wasn’t even sure if this was the right approach

minor zealot
#

I don't think that's the best approach. I'd use a grid layout group as suggested earlier and let it organize the items into rows/columns. It would try to fit them based on the object width.

I'm not sure what the cause of your current issue. It might be related to wrong timing or canvas scaling. I don't even see any logs in your code, so I'm not sure if the screenshot with logs that you shared is even reliable.

simple holly
#

I will attempt to fix this mess with a grid component then! Thanks for the advice

simple holly
#

I just did some messing around and since Grid Layout Group has Cell Size, it doesn't really work for my case, since items are random sizes.

#

If they were uniformly sized, it works perfectly.

simple holly
simple holly