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 /
This post has been wikified, any user with enough reputation can edit it.
avatar image
1
Question by YossiWF · Jan 20, 2015 at 03:37 AM · guitextscreenboundsunitygui

How can I get the on-screen render bounds of a Unity 4.6 GUI component whose canvas is set to World Space?

The answer here http://answers.unity3d.com/questions/49943/is-there-an-easy-way-to-get-on-screen-render-size.html doesn't work in this situation because a GUI Components are drawn using CanvasRenderer Components, which, unlike Renderer Components, don't offer a way to get bounds.

RectTransform has GetWorldCorners(), but the numbers it's returning for my Text Component seem to have no connection to its actual world bounds. (It might be returning the corner positions in canvas space, but I'm not entirely sure.)

If anyone is curious about the context for this question -- I'm trying to keep a text field to a constant size from the user's perspective no matter how close to or far from the camera it is. (Distance matters here because I'm rendering with stereoscopy.)

Thanks in advance!

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
0

Answer by Local-Minimum-2 · Aug 01, 2016 at 02:52 PM

I have a partial solution to this problem. But the problem isn't trivial since a UI component can be rotated both in the canvas plane as well as rotated in relation to the plane. Such rotations makes the bounding box either contain things outside the UI element or not the full element. The element itself can also be partially outside the canvas. Finally the canvas, if it's not a "Screen Space - Overlay" can be partially outside and rotated with respect to the camera.

My solution, only deals with "Screen Space - Overlay" and defining the outer bounding box of rotated UI element. There's some extra code in the end because I use it for making partial screenshots that you can disregard:

 using UnityEngine;
 using System.Linq;
 
 public enum OverflowMode { Crop,  Overflow};
 public enum BoxMode { Outer, Inner};
 
 public static class ScreenShot {
 
     /// <summary>
     /// Captures part of the screen.
     /// 
     /// Uses BoxMode.Outer and OverflowMode.Crop for both Canvas and Screen.
     /// 
     /// NOTE: It must be called during end of frame from coroutine yielding NewEndOfFrame.
     /// NOTE: It only is tested to work for Screen Overlay canvas, Camera parameter is kept for future expansions beyond such canvases.
     /// </summary>    
     /// <param name="transform">Transform to use for screenshot bounds</param>
     /// <param name="cam">Camera (not in use)</param>
     /// <param name="callback">Method that will get the texture as parameter when texture has been filled.</param>
     public static void CaptureByBounds(
     RectTransform transform, Camera cam, System.Action<Texture2D> callback)
     {
         CaptureByBounds(transform, cam, callback, BoxMode.Outer, OverflowMode.Crop, OverflowMode.Crop);
     }
 
     /// <summary>
     /// Captures part of the screen.
     /// 
     /// NOTE: It must be called during end of frame from coroutine yielding NewEndOfFrame.
     /// NOTE: It only is tested to work for Screen Overlay canvas, Camera parameter is kept for future expansions beyond such canvases.
     /// </summary>
     /// <param name="transform">Transform to use for screenshot bounds</param>
     /// <param name="cam">Camera (not in use)</param>
     /// <param name="callback">Method that will get the texture as parameter when texture has been filled.</param>
     /// <param name="boxMode">How to box the RectTransform when rotated</param>
     /// <param name="canvasOverflowMode">If Rect should be Cropped if it overflows canvas</param>
     /// <param name="screenOverflowMode">If Rect should be Cropped if it overflows screen</param>
     public static void CaptureByBounds(
         RectTransform transform, Camera cam, System.Action<Texture2D> callback, BoxMode boxMode, OverflowMode canvasOverflowMode, OverflowMode screenOverflowMode)
     {
 
         //Corners as positions of canvas
         Vector3[] corners = GetCorners(transform);
 
         Rect rect = BoxCorners(corners, boxMode);
 
         var c = transform.GetComponentsInParent<Canvas>().Last();
         if (canvasOverflowMode == OverflowMode.Crop)
         {
             rect = CropRectToInsideOther(rect, c.pixelRect);
         }
 
         if (screenOverflowMode == OverflowMode.Crop)
         {
             rect = CropRectToInsideOther(rect, new Rect(0, 0, Screen.width, Screen.height));
         }

         //It is "rect" that details position and size of the UI element in pixels on the screen.
 
         //Capture screen shot
         Texture2D tex = new Texture2D(Mathf.RoundToInt(rect.width), Mathf.RoundToInt(rect.height));
         tex.ReadPixels(rect, 0, 0);
         tex.Apply();
 
         //Let the callback get the captured texture
         callback(tex);
     }
 
     /// <summary>
     /// Gets the corners of a RectTransform in GlobalSpace.
     /// </summary>
     /// <param name="transform"></param>
     /// <returns>Array of corner points</returns>
     public static Vector3[] GetCorners(RectTransform transform)
     {
         //Bounds
         Vector2 min = transform.rect.min;
         Vector2 max = transform.rect.max;
 
         //The corners
         var A = transform.TransformPoint(min);
         var B = transform.TransformPoint(new Vector3(min.x, max.y));
         var C = transform.TransformPoint(max);
         var D = transform.TransformPoint(new Vector3(max.x, min.y));
 
         //Corners in canvas space
         return new Vector3[] { A, B, C, D };
     }
 
     /// <summary>
     /// Method to create a non-rotated bounding box based on corner data
     /// 
     /// NOTE: Only BoxMode.Outer is supported at the moment.
     /// </summary>
     /// <param name="corners">Array of corner points</param>
     /// <param name="mode">Boxing mode.</param>
     /// <returns>Bounding rect</returns>
     public static Rect BoxCorners(Vector3[] corners, BoxMode mode)
     {
         //Screen rect
         float x = 0;
         float y = 0;
         int w = 0;
         int h = 0;
 
         //Because rect could be skewed (by rotations) in the camera's view plane
         //The rect could eith be the Outer (capture everything inside the RectTransform)
         //or Inner (have the maximum size without capturing anything outside the RectTransform)
         if (mode == BoxMode.Outer)
         {
             x = corners.Select(v => v.x).Min();
             y = corners.Select(v => v.y).Min();
             w = Mathf.CeilToInt(corners.Select(v => v.x).Max() - x);
             h = Mathf.CeilToInt(corners.Select(v => v.y).Max() - y);
         }
         else {
             throw new System.NotImplementedException("Sorry don't need this one");
         }
 
         return new Rect(x, y, w, h);
     }
 
     /// <summary>
     /// Crops the first Rect so it is fully contained within the second.
     /// </summary>
     /// <param name="A">Rect to be cropped if needed</param>
     /// <param name="B">Bounding rect</param>
     /// <returns>Cropped rect</returns>
     public static Rect CropRectToInsideOther(Rect A, Rect B)
     {
 
         var ret = new Rect(Mathf.Max(A.x, B.x), Mathf.Max(A.y, B.y), 0, 0);
         ret.width = Mathf.Min(A.width, B.xMax - ret.x);
         ret.height = Mathf.Min(A.height, B.yMax - ret.y);
         return ret;
     }
 
     /// <summary>
     /// Method to write Texture2D to file.
     /// </summary>
     /// <param name="tex">The texture</param>
     /// <param name="path">File path</param>
     public static void WriteToFile(Texture2D tex, string path)
     {
 
         byte[] bytes = tex.EncodeToPNG();
         System.IO.FileStream f = System.IO.File.OpenWrite(path);
         f.Write(bytes, 0, bytes.Length);
         f.Close();
 
     }
 }
Comment
Add comment · 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

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

How to clear a GUI Label 1 Answer

How to set text(timer) to a fixed place 1 Answer

keep gui text object in the corner of the screen regardless of resolution 2 Answers

Resize text bassed on screen resolution 1 Answer

How can I add "..." to GUI.Label if it goes past its bounds? 1 Answer


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