Получите позицию UnityEngine.UI.Images в screenSpace и вычислите нормализованное смещение (внутри холста наложения)

Проблема:

упрощенный

Учитывая UnityEngine.Ui.Image Как найти положение X, Y нормализованного смещения (например, 0,4, 0,3 от верхнего левого) внутри этого изображения в единицах ScreenSpace, таких как 400 300

Думаю, мне нужно найти верхнее левое значение ScreenSpace, а затем зная, что отображаемый общий размер изображения соответствует нормализованным смещениям по фактическому размеру, выраженному в пикселях.

Рисунок 1: Figure 1:

На рисунке 2 показаны нормализованные Оффсеты, которые должны использоваться

Рисунок 2: An example stored Rect "offset"

Таким образом, в precis мне нужно найти смещение в пикселях ScreenSpace верхнего слоя фона Rect, который я сохранил против изображения.

Я признаю, что это, вероятно, комбинация Camera.main.ViewportToWorldPoint() и некоторая ссылка на границы, возможно, масштабируя ее по backgroundImage.sprite.pixelsPerUnit?

Стремитесь представить себе, как это сделать.

Спасибо

Ответ 1

Я думаю, у вас нет никакого масштаба или поворота в родителях изображения, а позиция Y равна 0.

Сначала вы можете получить положение верхнего левого угла изображения с помощью rectTransform.GetWorldCorners():

    //Upper left corner
    Vector3[] v = new Vector3[4];
    image.rectTransform.GetWorldCorners(v);
    var recPos = v[1];

Затем вам необходимо преобразовать нормализованное смещение в мировое пространство, смещенное на соотношение между размером вашего изображения и размером прямоугольника и добавьте положение верхнего левого угла:

    var recWidth = image.rectTransform.sizeDelta.x;
    var imgWidth = image.sprite.texture.width;
    var realOffsetX = offsetX * (recWidth / imgWidth);
    var realPosX = recPos.x + realOffsetX;

(Это та же самая формула для координаты Y, но вы должны вычесть по вашему отношению realOffsetY потому что смещение рассчитывается из верхнего левого угла)

Вот полный метод:

private Vector3 GetPositionOffset(Image image, float offsetX, float offsetY)
{
    //Upper left corner
    Vector3[] v = new Vector3[4];
    image.rectTransform.GetWorldCorners(v);
    var recPos = v[1];

    //X coordinate
    var recWidth = image.rectTransform.sizeDelta.x;
    var imgWidth = image.sprite.texture.width;
    var realOffsetX = offsetX * (recWidth / imgWidth);
    var realPosX = recPos.x + realOffsetX;

    //Y coordinate
    var recHeight = image.rectTransform.sizeDelta.y;
    var imgHeight = image.sprite.texture.height;
    var realOffsetY = offsetY * (recWidth / imgWidth);
    var realPosY = recPos.y - realOffsetY;

    //Position
    return new Vector3(realPosX, realPosY, image.transform.position.z);
}

Затем, если вы хотите, чтобы это пространство мира отображалось на экране, просто используйте метод камеры:

camera.WorldToScreenPoint(positionOffset);