Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save caneva20/5c5b8950601aac269d34eefbf1be01e9 to your computer and use it in GitHub Desktop.
Save caneva20/5c5b8950601aac269d34eefbf1be01e9 to your computer and use it in GitHub Desktop.
A small Unity helper class to convert viewport, screen or world positions to canvas space.
using UnityEngine;
/// <summary>
/// Small helper class to convert viewport, screen or world positions to canvas space.
/// Only works with screen space canvases.
/// </summary>
/// <example>
/// objectOnCanvasRectTransform.anchoredPosition = specificCanvas.WorldToCanvasPoint(worldspaceTransform.position);
/// </example>
public static class CanvasPositioningExtensions {
public static Vector3 WorldToCanvasPosition(this UnityEngine.Canvas canvas, Vector3 worldPosition, Camera camera) {
var viewportPosition = camera.WorldToViewportPoint(worldPosition);
return canvas.ViewportToCanvasPosition(viewportPosition);
}
public static Vector3 ScreenToCanvasPosition(this UnityEngine.Canvas canvas, Vector2 screenPosition) {
var viewportPosition = new Vector2(screenPosition.x / Screen.width, screenPosition.y / Screen.height);
return canvas.ViewportToCanvasPosition(viewportPosition);
}
public static Vector3 ViewportToCanvasPosition(this UnityEngine.Canvas canvas, Vector2 viewportPosition) {
//Gets the canvas's RectTransform
//canvas.GetComponent<RectTransform>() would work too,
//but since Transform of a UI Element is already a RectTransform
//I prefer to use cast instead to avoid the overhead of a GetComponent
var canvasTransform = (RectTransform) canvas.transform;
//Viewport positions ranges from 0 to 1
//Being (0, 0) the bottom left corner
//and (1, 1) the top right corner of the viewport.
//
//The sizeDelta of a canvas is the same as the screen resolution it is currently on.
//In a screen of 800x600, the canvas would have a sizeDelta of (x:800, y:600) too!
//
//With that information, we can "cast" a value from a viewport to its relative position on an (Unscaled) canvas
//Vector2.Scale or Vector3.Scale does just that (by simple multiplying each axis from A with the same axis from B)
var scaled = Vector2.Scale(viewportPosition, canvasTransform.sizeDelta);
//If a CanvasScaler is being used, by just doing the above is not enough.
//By scaling the result from above (again) with the scale of the canvas we can fix the position to account for canvas scaling
return Vector2.Scale(scaled, canvasTransform.localScale);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment