Search Unity

[SOLVED] WorldToScreenPoint behaviour

Discussion in 'Immediate Mode GUI (IMGUI)' started by acropole, Jun 16, 2010.

  1. acropole

    acropole

    Joined:
    Aug 13, 2009
    Posts:
    171
    Hi,

    With the following code :

    Code (csharp):
    1.     private void DrawTargets()
    2.     {
    3.         foreach (Pawn pawn in m_Targets)
    4.         {
    5.             Vector3 pos = camera.WorldToScreenPoint(pawn.transform.position);
    6.             float size = Mathf.Clamp(10000 / (pos.z + 1), 4, 32);
    7.  
    8.             Texture2D tex = targetsTex;
    9.             if (size <= 16) tex = targetsTex2;
    10.  
    11.             Rect rect;
    12.             if (pos.z < 0)
    13.             {
    14.                 return;
    15.             }
    16.             else
    17.             {
    18.                 if (pos.x <= 0)             tex = pawn.m_TargetLeft;
    19.                 else if (pos.x >= camera.pixelWidth) tex = pawn.m_TargetRight;
    20.                 else if (pos.y <= 0)    tex = pawn.m_TargetDown;
    21.                 else if (pos.y >= camera.pixelHeight) tex = pawn.m_TargetUp;
    22.             }
    23.  
    24.             rect = new Rect(pos.x - size / 2, camera.pixelHeight - (pos.y + size / 2), size, size);
    25.             GUI.DrawTexture(rect, tex);
    26.         }
    27.     }
    28.  
    Everything happens like if z < 0, but the objects are not behind the camera.

    The expected result first, and the result after :
     

    Attached Files:

  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    The doc page is a bit misleading here. The Z coordinate returned by WorldToScreenPoint is not the distance of the screen pixel from the camera but rather the distance from the camera to the XY plane at that pixel position. You can test if an object is in front of the camera or behind by taking the dot product of the object's heading with the camera's transform.forward vector:-
    Code (csharp):
    1. var heading = target.transform.position - camera.transform.position;
    2.  
    3. if (Vector3.Dot(camera.transform.forward, heading > 0) {
    4.     // Object is in front.
    5. }
     
    BinaryBanana and ewanmellor like this.
  3. acropole

    acropole

    Joined:
    Aug 13, 2009
    Posts:
    171
    Thank you.

    This is my new code. It works as expected :

    Code (csharp):
    1.     private void DrawTargets()
    2.     {
    3.         Vector3 pos, campos;
    4.         Texture2D tex;
    5.         float size;
    6.         Rect rect = new Rect(0,0,0,0);
    7.  
    8.         foreach (Pawn pawn in m_Targets)
    9.         {
    10.             pos = camera.WorldToScreenPoint(pawn.transform.position);
    11.             campos = pawn.transform.position - camera.transform.position;
    12.  
    13.             size = Mathf.Clamp(10000 / (pos.z + 1), 8, 32);
    14.  
    15.             tex = targetsTex;
    16.  
    17.             if (size <= 16) tex = targetsTex2;
    18.  
    19.  
    20.             if (Vector3.Dot(camera.transform.TransformDirection(Vector3.forward), campos) > 0)
    21.             {
    22.                 if (pos.x <= 0) tex = pawn.m_TargetLeft;
    23.                 else if (pos.x >= camera.pixelWidth) tex = pawn.m_TargetRight;
    24.                 else if (pos.y <= 0) tex = pawn.m_TargetDown;
    25.                 else if (pos.y >= camera.pixelHeight) tex = pawn.m_TargetUp;
    26.  
    27.                 rect.x = Mathf.Clamp(pos.x, 0, camera.pixelWidth) - size / 2;
    28.                 rect.y = camera.pixelHeight - (Mathf.Clamp(pos.y, 0, camera.pixelHeight) + size / 2);
    29.             }
    30.             else
    31.             {
    32.                 if (pos.x <= camera.pixelWidth / 2)
    33.                 {
    34.                     tex = pawn.m_TargetLeft;
    35.                     rect.x = 0;
    36.                     rect.y = camera.pixelHeight - (Mathf.Clamp(pos.y, 0, camera.pixelHeight) + size / 2);
    37.                 }
    38.                 else
    39.                 {
    40.                     tex = pawn.m_TargetRight;
    41.                     rect.x = 1;
    42.                     rect.y = camera.pixelHeight - (Mathf.Clamp(pos.y, 0, camera.pixelHeight) + size / 2);
    43.                 }
    44.  
    45.                 if (pos.y <= camera.pixelHeight / 2)
    46.                 {
    47.                     tex = pawn.m_TargetDown;
    48.                     rect.y = 0;
    49.                     rect.x = Mathf.Clamp(pos.x, 0, camera.pixelWidth) - size / 2;
    50.                 }
    51.                 else
    52.                 {
    53.                     tex = pawn.m_TargetUp;
    54.                     rect.y = 1;
    55.                     rect.x = Mathf.Clamp(pos.x, 0, camera.pixelWidth) - size / 2;
    56.                 }
    57.  
    58.             }
    59.  
    60.             rect.width = rect.height = size;
    61.  
    62.             GUI.DrawTexture(rect, tex);
    63.         }
    64.     }
     
  4. BinaryBanana

    BinaryBanana

    Joined:
    Mar 17, 2014
    Posts:
    81
    Thank you. This is still helping people :) I used "Z" initially and it didn't solve the problem. I hope Unity will update the doc or explain better how to use that value.