Skip to content

Instantly share code, notes, and snippets.

@FlaShG
Last active July 12, 2024 20:51
Show Gist options
  • Save FlaShG/ac3afac0ef65d98411401f2b4d8a43a5 to your computer and use it in GitHub Desktop.
Save FlaShG/ac3afac0ef65d98411401f2b4d8a43a5 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>
/// <code>
/// objectOnCanvasRectTransform.anchoredPosition = specificCanvas.WorldToCanvasPoint(worldspaceTransform.position);
/// </code>
/// </example>
public static class CanvasPositioningExtensions
{
public static Vector3 WorldToCanvasPosition(this Canvas canvas, Vector3 worldPosition, Camera camera = null)
{
if (camera == null)
{
camera = Camera.main;
}
var viewportPosition = camera.WorldToViewportPoint(worldPosition);
return canvas.ViewportToCanvasPosition(viewportPosition);
}
public static Vector3 ScreenToCanvasPosition(this Canvas canvas, Vector3 screenPosition)
{
var viewportPosition = new Vector3(screenPosition.x / Screen.width,
screenPosition.y / Screen.height,
0);
return canvas.ViewportToCanvasPosition(viewportPosition);
}
public static Vector3 ViewportToCanvasPosition(this Canvas canvas, Vector3 viewportPosition)
{
var centerBasedViewPortPosition = viewportPosition - new Vector3(0.5f, 0.5f, 0);
var canvasRect = canvas.GetComponent<RectTransform>();
var scale = canvasRect.sizeDelta;
return Vector3.Scale(centerBasedViewPortPosition, scale);
}
}
@ilibaz
Copy link

ilibaz commented Sep 30, 2020

awesome! saved me a lot of time 💯

@juamarCas
Copy link

Hey excellent work! it saved me a lot!

@fivefans
Copy link

This is great! I have a big need to know what a UI Image on the canvas would be in World Space. Could someone please help me with this? A CanvasToWorldPosition. Thank you. -- Jeff

@fivefans
Copy link

fivefans commented Sep 23, 2021

I needed world coordinates of different UI elements that was on a Canvas set to Screen Space - Camera. That was I could move the game objects to the location in the HUD and make them disappear once they reached the location. My game is 2D and it works exactly as I needed now. I hope this helps.

UICamera is my camera used for the UI (Screen Space - Camera) setting. I don't use Overlay or World canvas.
thisCanvas is the canvas in the scene.

var position = UICamera.WorldToScreenPoint(MyUIObject.transform.position); position.z = (thisCanvas.transform.position - UICamera.transform.position).magnitude; theLocationOfUIObjectInWorldSpace = Camera.main.ScreenToWorldPoint(position);

@Maesla
Copy link

Maesla commented Mar 4, 2022

Hello!

This is a little modification in case that the camera is not drawn in the 100% of the screen, using the viewport rect

    public static Vector3 WorldToCanvasPosition(this Canvas canvas, Vector3 worldPosition, Camera camera = null, bool useNormalizeViewPort = false)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        
        var viewportPosition = camera.WorldToViewportPoint(worldPosition);
        
        if (useNormalizeViewPort)
        {
            Rect normalizedViewPort = camera.rect;
            viewportPosition.x = viewportPosition.x * normalizedViewPort.width + normalizedViewPort.x;
            viewportPosition.y = viewportPosition.y * normalizedViewPort.height + normalizedViewPort.y;
        }
        
        return canvas.ViewportToCanvasPosition(viewportPosition);
    }

Thanks!

@TungHoangDao
Copy link

Awsome it works for me, just be care about your canvas anchor point. (from ViewportToCanvasPosition its currently using 0.5 0.5), but in my case its 0 1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment