I have a scene with a two camera setup. The main camera is perspective, and displays a UI that includes a panel with a render texture (render texture does not take up the entire UI). The Render Texture is created by another camera, which is orthographic, looking down -y, and provides a god’s eye view of the world. I have objects in the world and need to take their world position and translate them into screen space positions of the first camera to use for UI buttons, parented to the render texture panel (so that their positions match the world positions of the objects within the render texture).
using UnityEngine;
using UnityEngine.UI;
public class PositionObjectOnWorldImage : MonoBehaviour
{
public Camera worldCamera; //world camera with RenderTexture
public RectTransform worldImage; //RawImage which shows RenderTexture from camera
RectTransform helper; //object to help with transformations
void Start()
{
helper = (new GameObject ("helper", typeof(RectTransform))).GetComponent<RectTransform>();
helper.SetParent (worldImage, false);
helper.anchorMin = Vector2.zero;
helper.anchorMax = Vector2.zero;
}
public Vector3 GetPositionOnUI(Vector3 worldPosition)
{
//first we get screnPoint in camera viewport space
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint (worldCamera, worldPosition);
//then transform it to position in worldImage using its rect
Vector2 positionInImage = new Vector2 (screenPoint.x * worldImage.rect.width / worldCamera.pixelWidth,
screenPoint.y * worldImage.rect.height / worldCamera.pixelHeight);
//after positioning helper to that spot
helper.anchoredPosition = positionInImage;
//... return 3D position of that helper for any other RectTransform.position to use
return helper.position;
}
}
For improving speed: worldImage.rect.width / worldCamera.pixelWidth and worldImage.rect.height / worldCamera.pixelHeight should be calculated once, outside the method, and only recalculated if any of those dimensions change.
Incidently, if worldImage.rect is used to set size of world camera render target to always be 1:1, it can immediately be: helper.anchoredPosition = screenPoint;
The icons are slightly off, moreso in the x direction than the y (they appear above and to the right of where they should be). I have the anchor on the panel set to the lower left corner.