Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How to convert measure in pixel to 3D space units ?

Discussion in 'Scripting' started by danielesuppo, Aug 14, 2023.

  1. danielesuppo

    danielesuppo

    Joined:
    Oct 20, 2015
    Posts:
    331
    Hello,
    I have a GameObject that is outside of the camera, and I should move the Camera just a little bit to frame this GameObject.
    I can get its (negative or positive) offset X and Y screen position in pixel, but I can't understand how I could convert them in global units, without the need to calculate the difference from the screen borders.
    I think that it should be quite easy to simply translate a measure in pixel to 3D units, so I'm thinking that I'm getting more and more stupid, and that's why I'm asking for your help :)
    P.S. I don't have to convert a screen point to 3D units (I would have just used "ScreenToWorldPoint"), I need to convert a measure
    Many thanks!
     
  2. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
  3. danielesuppo

    danielesuppo

    Joined:
    Oct 20, 2015
    Posts:
    331
    Unfortunately I have to know the offset distance before to move the Camera...
    anyway this is my solution (it's not perfect but it work)

    Code (CSharp):
    1. public Vector3 GetDistanceOnCameraPlane(Vector3 pos1, Vector3 pos2, Camera camera = null)
    2.     {
    3.         Camera cam = camera ? camera : Camera.main;
    4.  
    5.         Vector3 cameraToP1 = (pos1 - cam.transform.position);
    6.         Vector3 cameraToP2 = (pos2 - cam.transform.position);
    7.  
    8.         Vector3 cameraForward = cam.transform.forward;
    9.         Vector3 cameraRight = mainCamera.transform.right;
    10.         Vector3 cameraUp = mainCamera.transform.up;
    11.  
    12.         float distanceX = Vector3.Dot(cameraToP1, cameraRight) - Vector3.Dot(cameraToP2, cameraRight);
    13.         float distanceY = Vector3.Dot(cameraToP1, cameraUp) - Vector3.Dot(cameraToP2, cameraUp);
    14.         float distanceZ = Vector3.Dot(cameraToP1, cameraForward) - Vector3.Dot(cameraToP2, cameraForward);
    15.  
    16.         return new Vector3(distanceX, distanceY, distanceZ);
    17.     }
    18.  
    19. public void MoveTheCameraWithOffset()
    20.     {
    21.         Vector3 pointInside = mainCamera.WorldToScreenPoint(point1.position);
    22.         Vector3 pointOutside = mainCamera.WorldToScreenPoint(point2.position);
    23.         Vector3 dist = GetDistanceOnCameraPlane(point1.position, point2.position);
    24.  
    25.         float screenDistanceX, pointOutsideOffsetX, screenDistanceY, pointOutsideOffsetY;
    26.         float marginX = Screen.width * screenMargin;
    27.         float marginY = Screen.height * screenMargin;
    28.  
    29.         if (pointOutside.x < 0)
    30.         {
    31.             screenDistanceX = pointInside.x + Mathf.Abs(pointOutside.x) - marginX;
    32.             pointOutsideOffsetX = Mathf.Abs(pointOutside.x) + marginX;
    33.            
    34.         }
    35.         else
    36.         {
    37.             screenDistanceX = pointOutside.x - pointInside.x - marginX;
    38.             pointOutsideOffsetX = pointOutside.x - Screen.width + marginX;
    39.         }
    40.  
    41.         if (pointOutside.y < 0)
    42.         {
    43.             screenDistanceY = pointInside.y + Mathf.Abs(pointOutside.y) - marginY;
    44.             pointOutsideOffsetY = Mathf.Abs(pointOutside.y) + marginY;
    45.            
    46.         }
    47.         else
    48.         {
    49.             screenDistanceY = pointOutside.y - pointInside.y - marginY;
    50.             pointOutsideOffsetY = pointOutside.y - Screen.height + marginY;
    51.         }
    52.  
    53.         /// get the local Camera X offset
    54.         float offsetInWorldUnitsX = (-1 / (screenDistanceX / pointOutsideOffsetX)) * dist.x;
    55.  
    56.         /// get the local Camera Z offset
    57.         float cameraPitchRadians = mainCamera.transform.localEulerAngles.x * Mathf.Deg2Rad;
    58.         float projectedDistanceZ = dist.y / Mathf.Cos(cameraPitchRadians);
    59.         float offsetInWorldUnitsY = (-1 / (screenDistanceY / pointOutsideOffsetY)) * projectedDistanceZ;
    60.  
    61.         /// we want to avoid a position that is inside the screen
    62.         if (pointOutside.x > 0 && pointOutside.x < Screen.width) offsetInWorldUnitsX = 0f;
    63.         if (pointOutside.y > 0 && pointOutside.y < Screen.height) offsetInWorldUnitsY = 0f;
    64.  
    65.  
    66.         mainPivot.position += transform.right * offsetInWorldUnitsX;
    67.         mainPivot.position += transform.forward * offsetInWorldUnitsY;
    68.     }