Search Unity

Pixel Perfect Conversion from World Space to SceneView UI Coordinates

Discussion in 'Scripting' started by Xelnath, Jul 21, 2019.

  1. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    259
    SceneView.current.camera.WorldToScreenPoint() cannot be trusted. It consistently returns values that are malformed if you are using a perspective camera (as the editor does by default).

    Use this to correct the distortion and position a UI element anchored to the object in world space during an OnSceneGUI command.

    Code (CSharp):
    1. public static partial class StaticUnityEditorHelper
    2. {
    3.     public static Vector3 SceneViewWorldToScreenPoint(SceneView sv, Vector2 worldPos)
    4.     {
    5.         var style = (GUIStyle)"GV Gizmo DropDown";
    6.         Vector2 ribbon = style.CalcSize(sv.titleContent);
    7.  
    8.         Vector2 sv_correctSize = sv.position.size;
    9.         sv_correctSize.y -= ribbon.y; //exclude this nasty ribbon
    10.  
    11.         //gives coordinate inside SceneView context.
    12.         // WorldToViewportPoint() returns 0-to-1 value, where 0 means 0% and 1.0 means 100% of the dimension
    13.         Vector3 pointInView = sv.camera.WorldToViewportPoint(worldPos);
    14.         Vector3 pointInSceneView = pointInView * sv_correctSize;
    15.         var p1 = pointInSceneView;
    16.         p1.y = sv.position.height - p1.y;
    17.  
    18.         return p1;
    19.     }
    20. }
    Example usage:

    Code (csharp):
    1.  
    2.  
    3.  
    4.         Handles.BeginGUI();
    5.  
    6.         var pos = StaticUnityEditorHelper.SceneViewWorldToScreenPoint(scene, t.transform.position);
    7.         Rect rect2 = new Rect(pos.x, pos.y, 100, 50);
    8.         EditorGUI.DrawRect(rect2, Color.white);
    9.  
    10.         if (Event.current.type == EventType.MouseDown && rect2.Contains(Event.current.mousePosition))
    11.         {
    12.             Debug.Log("press");
    13.         }
    14.  
    15.         Handles.EndGUI();
    16.