Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
1
Question by bob2356 · Aug 14, 2013 at 01:51 PM · layout

How to use GUILayoutUtility.GetRect() properly?

Hello all,

I am trying to make a simple component that would display a text of arbitrary length at given position of the screen, with the possibility to wordwrap at a given width and/or to display a background.

Here's the code:

 public class TextDisplayer : ScaledGUI
 {
     public Rect Area;
     public GameObject Reference;
     public string Text;
     public string CustomStyle;
     public bool DisplayAsBox;
     
     protected override void OnScaledGUI()
     {
         GUIContent content = new GUIContent(Text);
         GUIStyle style = (CustomStyle != string.Empty) ? GUI.skin.GetStyle(CustomStyle) : (DisplayAsBox ? GUI.skin.box : GUI.skin.label);
         GUILayoutOption[] options = new GUILayoutOption[] {GUILayout.MaxWidth(Area.width)};
         
         Rect area = GUILayoutUtility.GetRect(content, style, options);
         area.x = Area.x;
         area.y = Area.y;
         if (Reference)
         {
             Vector3 refPos = WorldToScaledGUIPoint(Reference.transform.position);
             area.x += refPos.x;
             area.y += refPos.y;
         }
 
         GUILayout.BeginArea(area);
         if (DisplayAsBox)
         {
             GUILayout.Box(content, style, options);
         }
         else
         {
             GUILayout.Label(content, style, options);
         }
         GUILayout.EndArea();
     }
 }

The problem is: nothing is displayed!

If I set area.width and area.height manually to arbitrary values, it works well but I don't find this solution very elegant.

I found out here that OnGUI (from which OnScaledGUI is called in the parent ScaledGUI class) is called to times: one time for EventType.Layout, then one time for EventType.Repaint. During EventType.Layout, it is expected that GUILayoutUtility.GetRect() returns 0 values as the layout is not computed yet. But if I understood correctly, GUILayout calls don't do anything in that case, so it shouldn't be a problem. Yet, It doesn't work as expected and as long as I base my area on GUILayoutUtility.GetRect(), nothing shows up on screen. So I must obviously miss something here, and do something wrong.

Would anyone know what is wrong with my use of GUILayoutUtility.GetRect(), and how to fix it?

Comment
Add comment · Show 4
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 Jamora · Aug 14, 2013 at 08:06 PM 0
Share

You are not showing/telling where Area is initialized so I have to ask, is it initialized? Also, what does Debug.Log(area.ToString()); print out just before you call BeginArea?

avatar image bob2356 · Aug 16, 2013 at 01:37 PM 0
Share

TextDisplayer inherits from ScaledGUI, which inherits from $$anonymous$$onoBehavior. Area being a public member variable, it is initialized with the values entered in the Inspector.

Inspector

Regarding the logs, here's what I added:

         ...
         
         if (Event.current.type == EventType.Layout)
         {
             Debug.Log("Layout " + area.ToString());
         }
         else if (Event.current.type == EventType.Repaint)
         {
             Debug.Log("Repaint " + area.ToString());
         }
         else
         {
             Debug.Log ("Other event " + area.ToString());
         }
         GUILayout.BeginArea(area);
         
         ...

And here's what I get:

 Layout (x:421.11, y:301.78, width:1.00, height:1.00)
 Repaint (x:421.11, y:301.78, width:100.00, height:68.00)
 ...


avatar image Croustibat · Apr 11, 2014 at 12:11 PM 0
Share

Hey bob, I've got exactly the same problem as you: Rect given by a GetRect is behaving strangely, which gives sometimes really small widths and heights. Did you figure out what was going wrong?

avatar image bob2356 Croustibat · Apr 13, 2014 at 11:34 AM 0
Share

I never figured out why it would behave like this, but I found a workaround:

 Rect textArea = new Rect(Area.x, Area.y, Area.width, style.CalcHeight(content, Area.width));
 
 [...]
 
 if (DisplayAsBox)
 {
     GUI.Box(textArea, content, style);
 }
 else
 {
     GUI.Label(textArea, content, style);
 }

Hope this can help you.

1 Reply

· Add your reply
  • Sort: 
avatar image
7

Answer by fredericv · May 08, 2017 at 01:04 PM

@bob2356 @Croustibat

Hi,

There is a first call with EventType.Layout that registers all GUILayout requests, then just before the call with EventType.Repaint, the rect are calculated properly.

Thus, GUILayoutUtility.GetRect( ... ) will return a dummy rect on Layout phase (0, 0, 1, 1) and the correct rect on Repaint phase.

But, GUILayout.BeginArea(Rect) uses the size on the Layout phase (so the dummy (0, 0, 1, 1)).

One way to go, is to store the calculated rect on the Repaint phase and give it to GUILayout.BeginArea on the Layout phase.

You can try something like this:

 Rect m_AreaRect;
 
 void OnGUI()
 {
     ...
     var rect = GUILayoutUtility.GetRect(...);
     if (Event.current.type == EventType.Repaint)
         m_AreaRect = rect;
 
     GUILayout.BeginArea(m_AreaRect);
 
     ...
 }
Comment
Add comment · Show 3 · 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 Helical · Aug 22, 2019 at 10:47 AM 1
Share

A question posted in 2013, answered at 2017, and reused at 2019. This is actually very hard to find via Google the explanation and workaround these days. I did not even know to use Event.current.type or that it had any role at all with OnGUI development.

avatar image Bunny83 Helical · Jun 04, 2021 at 12:48 AM 0
Share

If you did not know that fundamental fact about the IMGUI system, you may want to read my IMGUI crash course.

avatar image JasonC_ · Jun 03, 2021 at 09:26 PM 0
Share

Still legit in 2021, lol.

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

21 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

Related Questions

Customizing Editor Interface 1 Answer

Is there a Floor Guide in Unity, and a Working View Reset feature? 2 Answers

How to listen for UI Resize Events 3 Answers

I don't understand "Child Force Expand" on uGUI 2 Answers

Horizontal Layout Group padding update via script 3 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