Search Unity

How to Get ScreenPoint from a Second Camera

Discussion in 'Scripting' started by John-B, May 29, 2015.

  1. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,262
    I have a second camera (orthographic, size 0.27) that shows a closeup of a control panel (in the scene) in its own pop-up panel, but I can't get the screen coordinates of the controls that show in that camera's view. The camera's viewport rect is X=0.71, Y=0.66, W=0.255, H=0.295, so it's a small window in the upper-right of the screen. See the attached diagram.

    When I use WorldToScreenPoint with that camera, to find the location of a control relative to a click, I get (3457.4, 621.7). The Y coordinate looks correct, compared to the mousePosition, but the X value is obviously way off on a 1024 x 768 screen. The X coordinate, based on the position of the mouse, should be around 860. ViewportToScreenPoint gives both X and Y values that are way too big.

    I tried multiplying the X value by a constant, but that only works for one particular view. I have several close-up views of several control panels located at different locations in the scene, and WorldToScreenPoint returns different values for each view. The close-up camera is always in the same exact position relative to the control panel, so the screen point of a particular control should always be the same in every view.

    How can I get the screen coordinates of objects in the second camera's viewport?

    Control-Panel-View.jpg
     
  2. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Here you go:

    Code (CSharp):
    1. public class test_cam : MonoBehaviour {
    2.  
    3.     public Camera cam;
    4.     RaycastHit hit;
    5.     Ray click_ray;
    6.     Vector3 hit_pos;
    7.     Vector3 screen_point;
    8.  
    9.     void Start () {
    10.  
    11.     }
    12.  
    13.     void Update ()
    14.     {
    15.         if (Input.GetMouseButtonUp(0))
    16.         {
    17.             click_ray = cam.ScreenPointToRay(Input.mousePosition);
    18.             if (Physics.Raycast(click_ray, out hit, 50))
    19.             {
    20.                 if (hit.collider.tag == "target")
    21.                 {
    22.                     hit_pos = hit.collider.transform.position;
    23.                     screen_point = cam.WorldToScreenPoint(hit_pos);
    24.                     print(screen_point);
    25.                 }
    26.             }
    27.         }
    28.     }
    29. }
     
  3. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    I guess I could have used hit.point also to get a more accurate hit position, but this is the basic idea
     
  4. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,262
    That's getting the world coordinate from a ray cast, then translating that point using WorldToScreenPoint. It might work, getting the world coordinate from a ray cast, but my situation is different. I have a rotating control knob, so in addition to knowing if I hit the control, I also need to know where my click was relative to the center of that control (to calculate the angle of the knob's rotation), both in screen coordinates.

    Your code tells me where on the object I clicked, which is not the problem. I still need to know where that click was relative to the object's center. That's what doesn't work using the object's actual world position and WorldToScreenPoint.

    This is code I've used for rotating controls, and it's always worked. But in order for it to work correctly, the click point and the control's center point need to be in the same coordinate space. Normally, WorldToScreenPoint works as it should, but for some reason it appears that when it's not the main camera, the value it returns is wrong, or at least not in the same screen coordinates as the mouse position.
     
    Last edited: May 30, 2015
  5. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Sorry if I am misunderstanding you, but my thinking is that you can determine the object's origin in world space with a raycast as well as the clicked position with hit.point. Then you should be able to determine the angle between those 2 by using:
    Code (CSharp):
    1. float angle = Mathf.Atan2(hit2.y-hit1.y, hit2.x-hit1.x)*180 / Mathf.PI;
    Have'nt tested it though...