I want to turn a RectTransform.rect into a world space Rect object. RectTransform doesn’t appear to have a method to convert the rectangle object to world coordinates. But I want something like the following.
myRectTransform.ConvertToWorldRect();
I want to turn a RectTransform.rect into a world space Rect object. RectTransform doesn’t appear to have a method to convert the rectangle object to world coordinates. But I want something like the following.
myRectTransform.ConvertToWorldRect();
Looks like you can chain together a few Unity API methods for some clever conversion. Example below includes support for modifying the Rect’s size based upon the current Canvas scale.
using UnityEngine;
using System.Collections;
static public class RectTransformExt {
/// <summary>
/// Converts RectTransform.rect's local coordinates to world space
/// Usage example RectTransformExt.GetWorldRect(myRect, Vector2.one);
/// </summary>
/// <returns>The world rect.</returns>
/// <param name="rt">RectangleTransform we want to convert to world coordinates.</param>
/// <param name="scale">Optional scale pulled from the CanvasScaler. Default to using Vector2.one.</param>
static public Rect GetWorldRect (RectTransform rt, Vector2 scale) {
// Convert the rectangle to world corners and grab the top left
Vector3[] corners = new Vector3[4];
rt.GetWorldCorners(corners);
Vector3 topLeft = corners[0];
// Rescale the size appropriately based on the current Canvas scale
Vector2 scaledSize = new Vector2(scale.x * rt.rect.size.x, scale.y * rt.rect.size.y);
return new Rect(topLeft, scaledSize);
}
}
More convenient solution:
public static class RectTransformExtensions
{
public static Rect GetWorldRect(this RectTransform rectTransform)
{
Vector3[] corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);
// Get the bottom left corner.
Vector3 position = corners[0];
Vector2 size = new Vector2(
rectTransform.lossyScale.x * rectTransform.rect.size.x,
rectTransform.lossyScale.y * rectTransform.rect.size.y);
return new Rect(position, size);
}
}
Thanks for the tip! Why we cannot use top right and bottom left corner to calculate the rect size?
public static class RectTransformExtensions {
public static Rect GetWorldRect(this RectTransform rectTransform) {
Vector3[] corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);
return new Rect(corners[0], corners[2] - corners[0]);
}
}
Seems to be working fine.
public static class RectTransformExtensions
{
public static Rect GetWorldRect(this RectTransform rectTransform)
{
var minX = float.MaxValue;
var minY = float.MaxValue;
var maxX = float.MinValue;
var maxY = float.MinValue;
var pool = ArrayPool<Vector3>.Shared;
var corners = pool.Rent(4);
rectTransform.GetWorldCorners(corners);
for (var i = 0; i < 4; i++)
{
var corner = corners[i];
minX = Mathf.Min(corner.x, minX);
minY = Mathf.Min(corner.y, minY);
maxX = Mathf.Max(corner.x, maxX);
maxY = Mathf.Max(corner.y, maxY);
}
pool.Return(corners);
var position = new Vector2(minX, minY);
var size = new Vector2(maxX - minX, maxY - minY);
return new Rect(position, size);
}
public static Rect GetLocalRect(this RectTransform rectTransform)
{
var worldRect = rectTransform.GetWorldRect();
var parent = rectTransform.parent;
var min = parent.InverseTransformPoint(worldRect.min);
var max = parent.InverseTransformPoint(worldRect.max);
return new Rect(min, max - min);
}
}