Search Unity

How to use Camera.ViewPortToWorldPoint

Discussion in 'Scripting' started by gantoine, Sep 25, 2017.

  1. gantoine

    gantoine

    Joined:
    Sep 24, 2017
    Posts:
    21
    Hello fellow Unity developers,

    I come seeking guidance on how to properly use Camera.ViewPortToWorldPoint. My understanding is that I can use this to convert a point on the viewport to a point in world space, but even after hours of searching I am having a difficult time finding information on how to properly use it.

    Yes, I did look at the Scripting API.

    Here is what I am trying to do: I want to take a position on the viewport and translate it to a position in world space so that I can use that information to set the transform position of a gameobject.

    I am working in 2D.

    Thank you in advance for your assistance.
     
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    What exactly are you struggling with? Syntax? Other results than expected? Provide more information and you'll get help.

    And yes, the method does exactly what you're after, note that this method is using normalized values instead of pixel values (for the latter you could use ScreenPointToWorld).
     
  3. LMan

    LMan

    Joined:
    Jun 1, 2013
    Posts:
    493
    Viewport space is great for all those times you don't want to deal with screen space. (for example: ALL the time.) No worries about how big or what resolution the screen is- because viewport space is relative. (0,0) is the lower left corner, (1,1) is the upper right- simple.

    Sometimes, you may need to get the world space coordinates of, say just off center screen- (.5, .45). Naturally, the screen is a 2D plane and world space is 3D, so the "z component is the distance of the resulting plane from the camera."
     
    BloodyIns likes this.
  4. gantoine

    gantoine

    Joined:
    Sep 24, 2017
    Posts:
    21
    Apologies if my ask was vague. Help with the syntax is specifically what I'm after. Thank you.
     
  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Syntax is pretty easy. Pretty much like @LMan has already explained.
    You only need to pass in a position of your view port, usually something in between (0,0) and (1,1) and a z value. The z value is used to determine a plane parallel to your view port, so that view port and said plane have a distance of z.

    What you'll get back is a Vector3 that describes the world position.

    The following script makes the object (e.g. a sprite for testing) cross your screen from the lower left to the upper right corner, it moves along the plane that is 1 unit (z = 1) in front of the camera.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Test : MonoBehaviour
    4. {
    5.     private float _progress;
    6.    
    7.     private void Update()
    8.     {
    9.         var nextPos = new Vector3(_progress, _progress, 1);
    10.         transform.position = Camera.main.ViewportToWorldPoint(nextPos);
    11.  
    12.         _progress += Time.deltaTime * 0.2f; // takes ~ 5 seconds to cross the screen
    13.     }
    14. }
    15.  
    Working with sprites, the only thing you should take note of is that z > nearClipPlane of the camera, otherwise it'll not be rendered.
    Working with 3D objects, you may want to make sure you do not choose a plane that is too close, otherwise you'll experience annoying visual effects ranging from non-rendering, flickering, to partly-rendererd meshes. Make sure you choose a reasonable distance that prevents these issues and also favors your gameplay mechanics.
     
    firebird721, IlyaKo and waikit97 like this.
  6. gantoine

    gantoine

    Joined:
    Sep 24, 2017
    Posts:
    21
    Suddoha,

    Thank you for your response. A follow-up question:

    Suppose that I just want to place a sprite at a specific position relative to the viewport like (0.1, 0.1) for near the bottom left corner. How would I write that?
     
  7. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    You should be able to answer this on your own, but I'll describe it roughly. Putting this into code will be your job. ;)

    First of all, if you want to place it at that specific position, it's a one-time action. You wouldn't need Update() for it, but you can use e.g. Start().

    Next, have a look at the snippet again. As mentioned, the method takes a Vector3. In my example, this Vector3 changes over time. You only need it to be (0.1f, 0.1f, z) where z should be a positive value. The _process variable is not needed, as you don't want to change its position.
     
    firebird721 likes this.
  8. gantoine

    gantoine

    Joined:
    Sep 24, 2017
    Posts:
    21
    Suddoha,

    I was successful in achieving my goal, but it seems I always need to establish a Vector3 as a variable and use the variable in my Start() code. Is it not possible to input a Vector 3 directly into my code in Start()? Trying the following does not work:

    Code (CSharp):
    1.         transform.position = Camera.main.ViewportToWorldPoint(0.1f, 0.1f, 1);
    2.  
    I know it's usually best practice to establish these things as variables, but I just want to know if it's possible.

    Thank you for your help.
     
  9. waikit97

    waikit97

    Joined:
    Mar 1, 2018
    Posts:
    1
    I know it's late but try
    Code (CSharp):
    1. transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0.1f, -0.1f, 1));
     
    firebird721 likes this.