Get size of stretched RectTransform

When working with Unity UI system, sometimes it is useful to know what the size of a given RectTransform is. Maybe you need to know how big a widget needs to be, or to see if a mouse pointer is within that given rect.

There are two ways to do so.

Using sizeDelta

RectTransform.sizeDelta

The catch with this is that it returns a size which is relative to the parent object, so it is possible to get zero/negative values if the RectTransform is smaller than the parent object. BUT, if the pivots of the transform that you are trying to measure coincide, then sizeDelta will return the actual size of the transform.

This is especially important to note when working with transforms that are set to stretch, because their pivots do not match up.

Using rect

RectTransform.rect

The other way to get the size of a RectTransform is to use its rect property. This one always returns the correct size of the transform, so I would suggest to use this whenever you need the size of a transform and don’t want to worry about how its pivots are set up.

The only problem with this approach occurs when you are instantiating new objects, like a prefab for a vertical list, and accessing their rect property on the same frame that they are created. Unity, in fact, takes one frame to re calculate the values, so you might end up with incorrect results if you do not wait.

I found two solutions to solve this problem.

Solution 1: Rebuild Canvases

Canvas.ForceRebuildCanvases()

If you need to call this only once then this is probably the easiest solution and the quickest. However, re-building canvases allocates quite a bit of memory, especially if it is called repeatedly when instantiating many objects for a list in your UI.

Solution 2: Wait one frame

You can do this in a couple of ways.

StartCoroutine(ReadRectSize);

IEnumerator ReadRectSize()
{
 // Read rect transform size....
}

Calling a Coroutine is a simple way to wait one frame to then grab the size of a RectTransform. The problem with this approach is that the implementation is less straight forward than rebuilding canvasses, since you will have to write a new method. However, it is still quite readable.

bool readRectSize = false;

void Update()
{
    if(readRectSize)
    {
        // read rect size...
        readRectSize = false;
    }
}
void InstantiateObjects()
{
     // create objects
     readRectSize = true;
}

If you don’t want to use Coroutines then the next solution is to use a Boolean flag. When instantiating objects you can set the flag and then check it on your Update function. This is the safest solution in terms of simplicity and memory allocation, but it comes at the cost of having to add an extra flag in your implementation.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.