Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Eno-Khaon · Apr 17, 2018 at 04:57 AM · rotationuicanvasscale

Rotating and Scaling "Stretched" UI Elements

First, as a preface, in order to enforce a minimum resolution on either axis for the UI Canvas, I'm currently taking an arbitrary dimension (let's say it's 1024), and performing the following transformation:

 CanvasScaler scaler = GetComponent<CanvasScaler>();
 float referenceSize = 1024.0f;
 scaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize;
 float wRatio = Screen.width / referenceSize;
 float hRatio = Screen.height / referenceSize;
 scaler.scaleFactor = Mathf.Min(wRatio, hRatio);


As can be see from my example, I'm ensuring that the Canvas is based around a Constant Pixel Size, then scaled (scaleFactor) so that the shorter dimension is 1024 pixels as its basis.


For the UI elements themselves ( RectTransform), I'm performing rotations by changing the position of the UI element ( localPosition and/or anchoredPosition), then simply rotating the UI element around its pivot point. In this regard, everything works just as intended.

However, I've run into a problem in attempting to properly honor alignment for a "stretched" RectTransform.

If a UI element is stretched horizontally all the way across the screen (at any resolution), it would have X anchors ( RT.anchorMin.x and RT.anchorMax.x) at 0 and 1 respectively, with Left and Right offsets of 0 (applied by RT.offsetMin.x and RT.offsetMax.x or RT.sizeDelta to combine them).

When such a UI Element is rotated 90 degrees, it will extend vertically by the same number of pixels naturally. In this regard, it would extend beyond the top and bottom of the screen on a Landscape screen aspect ratio or would take up only a portion of the height with a Portrait aspect ratio.

Therefore, in order to make up for the difference, each side needs to be drawn in based on the difference in pixel count extending toward each end of the screen. For example, if the Canvas size is 1024x2048 or 2048x1024, I have a +/- 1024-pixel difference to make up for upon rotating the UI element 90 degrees. By adjusting the offsets/ sizeDelta accordingly, this *SHOULD* result in the UI element stretching to fit the new " width" it's aligned to.

However, this has not been the case. Rather, much more problematically, this *HAS* been the case in a Landscape aspect ratio, whereas for Portrait, I must multiply that difference by the canvas height/width in order to properly fit.

This should be especially straightforward and simple ( width - height = the difference between them for sizeDelta to compensate), so I've been baffled, unable to figure out why there would be a difference in this calculation depending on whether the aspect ratio is Portrait or Landscape.
 // Canvas Rect Transform
 RectTransform crt = transform.parent as RectTransform;
 
 // negative to expand, positive to contract
 float sizeDeltaRotated = crt.rect.height - crt.rect.width;
 
 // When rotated 90 degrees...
 // -- Landscape
 thisRectTransform.sizeDelta = sizeDeltaRotated;
 // -- Portrait
 float hwRatio = crt.rect.height / crt.rect.width;
 thisRectTransform.sizeDelta = hwRatio * sizeDeltaRotated;


Why has this difference in calculation been necessary for me to get equivalent results? Has there been a behavior I've overlooked when defining the ScaleFactor in this manner, or have I been missing something else entirely?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Eno-Khaon · Apr 17, 2018 at 06:26 PM

Okay, I found the root of the problem.

Changing the Canvas' uiScaleMode doesn't take effect immediately. The changes will have propagated after one frame has passed, but that's no good...

Looks like I'll probably just need to compute the sizes myself instead of relying on the Canvas' height and width.


For reference, the reason I was seeing inconsistent scaling behavior is because I'd initially set up the UI using the Canvas Scale Mode " ScaleWithScreenSize". By using the script (mentioned at the start of my question) to resize the UI Elements, it was already successfully matching my current Scaling settings in the case of Landscape orientation ( matchWidthOrHeight value of 1 meant Unity was automatically accommodating Landscape aspect ratio ahead of time in this situation).

So, in the end, my solution is to simply calculate the new Canvas resolution, set those variables aside, and read from them without having to wait until the next frame for the Canvas to fully update.
 // Script on Canvas (Excerpt)
 private float fWidth;
 public float width
 {
     get
     {
         return fWidth;
     }
 }
 
 private float fHeight;
 public float height
 {
     get
     {
         return fHeight;
     }
 }
 
 void OnEnable()
 {
     float wRatio = Screen.width / referenceSize;
     float hRatio = Screen.height / referenceSize;
     float minScale = Mathf.Min(wRatio, hRatio);
     fHeight = Screen.height / minScale;
     fWidth = Screen.width / minScale;
 }


 // Script on UI element (Excerpt, unpolished)
 CanvasResize cr = transform.parent.GetComponent<CanvasResize>();
 sizeDeltaRotated = (cr.height - cr.width) + thisRectTransform.sizeDelta;


Yep, the solution was fundamentally the same as what I was already doing. I just hadn't realized that the Canvas wasn't updating in full immediately, so I was being given inaccurate data to work with from its RectTransform.

If anyone has any input regarding a means of updating the Canvas' RectTransform more immediately, I encourage you to bring it up; the more and more thorough information available here, the better. However, for all intents and purposes, this problem is solved.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eno-Khaon · Apr 17, 2018 at 09:06 PM 1
Share

Found a handy piece of information I didn't consider looking up until knowing that the Canvas updates at the end of a frame:

https://docs.unity3d.com/ScriptReference/Canvas.ForceUpdateCanvases.html

Edit: Scratch that. Once I tried it, that still didn't actually update the RectTransform upon use.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

160 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Why are the elements of my scrollview scaled different after refreshing? 0 Answers

Layout error after crash has effected canvas scaling 1 Answer

Why does my dynamically instantiated UI element have a different scale than the prefab it was instantiated from? 1 Answer

Scaling a menu bar 1 Answer

Keep the size of a gameobject on HUD changing Z depth 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges