- Home /
Is there a simple way to check if a UI element is fully visible on screen ?
I need to do this for two reasons : I want to make a draggable UI window but prevent it from being dragged outside the screen, and I also want to make sure my tooltips don't overflow from the screen and get cut.
How should I go about doing that ? Is there a way maybe to get the size of a UI element and the size of the Canvas and then compare them ? I feel like I'm missing something here.
Answer by fafase · Mar 09, 2015 at 01:06 PM
Are you using uGUI or legacy GUI?
You can get the rect of your UI element and get the four corners then the rect of the screen and do:
if(screenRect.Contains(pos0) )
{
// Inside
}
I'm using uGUI, and both of the elements I want to check are basically Panels. I'm not sure how I can get the screen rect, should I get it from the Canvas object ?
Screen rect is just:
Rect screenRect = new Rect (0,0, Screen.width, Screen.height);
Getting the rect if the UI elements seems to be more of a pain. There may be an easy way I have not yet found nor needed but otherwise it would have to be through getting the position then using the anchored position based on the parent you can find some data. Does not sound so easy so there should be an easy way to get those...
Thank you for your help. I found a way to do it, it's pretty basic right now but here's the idea :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class $$anonymous$$oveableWindow : $$anonymous$$onoBehaviour {
Vector3 lastPosition;
Rect screenRect;
void Start()
{
lastPosition = this.transform.position;
screenRect = new Rect(0f, 0f, Screen.width, Screen.height);
}
public void OnDrag()
{
this.transform.position = Input.mousePosition;
}
public void OnDrop()
{
Vector3[] objectCorners = new Vector3[4];
this.GetComponent<RectTransform>().GetWorldCorners(objectCorners);
bool isObjectOverflowing = false;
foreach (Vector3 corner in objectCorners)
{
if (!screenRect.Contains(corner))
{
isObjectOverflowing = true;
break;
}
}
if (isObjectOverflowing)
this.transform.position = lastPosition;
lastPosition = this.transform.position;
}
}
So basically it seems you can get the Rect Transform with GetComponent and then you get all the methods you need to compare a GUI element to the screen. Awesome.
Thanks again !
Saw it but was just getting a bunch of 0's. Well, u got it anyway.
This makes sense to me (in a way) but I am finding that where the objectCorners are in world coordinates my container rect are different so the test always fails?
Answer by marcojacovone · Sep 05, 2015 at 04:17 PM
Hi,
I use Canvas in Screen Space - Overlay option. To detect if a RectTransform is visible or out of the screen in my projects I use this solution:
void Update ()
{
Vector3[] v = new Vector3[4];
GetComponent<RectTransform>().GetWorldCorners (v);
float maxY = Mathf.Max (v [0].y, v [1].y, v [2].y, v [3].y);
float minY = Mathf.Min (v [0].y, v [1].y, v [2].y, v [3].y);
//No need to check horizontal visibility: there is only a vertical scroll rect
//float maxX = Mathf.Max (v [0].x, v [1].x, v [2].x, v [3].x);
//float minX = Mathf.Min (v [0].x, v [1].x, v [2].x, v [3].x);
if (maxY < 0 || minY > Screen.height) {
// Do Something that disable UI elements
} else {
// Do something that re-enable UI elements
}
}
This works for me. Hope helps.
Answer by Nodrap · Nov 12, 2015 at 02:53 PM
My solution is based on the above so credits due. This works with a canvas set as Screen space Camera.
Use this to create a test rect the size of the screen in some Awake fn using the canvas you want to test against:
Vector3 c1 = mainCanvas.worldCamera.ScreenToWorldPoint(Vector3.zero);
Vector3 c2 = mainCanvas.worldCamera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height));
Rect canvasRect = new Rect( c1, new Vector2(c2.x-c1.x, c2.y-c1.y));
Then I did tests on the UI element like this:
Vector3[] corners = new Vector3[4];
GetComponent<RectTransform>().GetWorldCorners(corners);
Rect rec = new Rect(corners[0].x, corners[0].y, corners[2].x-corners[0].x, corners[2].y-corners[0].y);
if (rec.Overlaps(canvasRect))
...
Answer by hamokshaelzaki · Dec 12, 2016 at 04:28 PM
Well, I have reached some good utility exist in Unity3d, I hope this helps:
RectTransformUtility.RectangleContainsScreenPoint
Answer by IgorAherne · Feb 04, 2018 at 05:46 AM
Here is a better way than all of the proposed:
https://forum.unity.com/threads/2-recttransforms-overlapping.515670/
"Better answer than all of the proposed" is subjective. I'd argue on its complexity and the fact that first comment is telling you how to improve. That you want to help is a good thing, but that claim...not a good thing.
That's my opinion and I am not going to discuss it! Also that comment in the forum is wrong
Your answer
Follow this Question
Related Questions
Determining the title bar height of a GUI Window 1 Answer
picture in picture 3d. 0 Answers
GUI.Window function not called anymore 1 Answer
How do I make GUI buttons draw more GUI objects when clicked? 2 Answers
GUI.Window function with variables? 3 Answers