Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

ScreenPointToRay + MousePosition

Discussion in 'Scripting' started by Divine Rage, Jan 10, 2010.

  1. Divine Rage

    Divine Rage

    Joined:
    Jan 10, 2010
    Posts:
    3
    Hi there,

    I'm messing around with Unity as a beginner, waiting primarily for my new laptop to arrive (3 days!), and I ran into a problem.

    I'm trying to instantiate objects (simple cube at the moment) at a point where I click with my mouse. I was reading through some docs, when I came across these pages;

    http://unity3d.com/support/documentation/ScriptReference/Input-mousePosition.html
    http://unity3d.com/support/documentation/ScriptReference/Camera.ScreenPointToRay.html

    The first one uses Input.Mouseposition as a Vector3 variable in Camera.ScreenPointToRay, which seems odd to me.
    Regardless, I've tried messing around with Debug.DrawLine and such, and ended up logging the RaycastHit.point value. Which is always at 0,0,0. To my knowledge it's supposed to return the world space coordinates of the ray's hit.

    I'm currently using this script;
    Code (csharp):
    1. var particle : GameObject;
    2. var debugraystart : Vector3;
    3. var debugrayend : Vector3;
    4.  
    5. function Update ()
    6. {
    7.     if (Input.GetButtonDown ("Fire1"))
    8.     {
    9.         var ray = Camera.main.ScreenPointToRay (Input.mousePosition); // Construct a ray from the current mouse coordinates
    10.         var hit : RaycastHit;
    11.        
    12.         if (Physics.Raycast (ray))
    13.         {
    14.             Debug.DrawLine (hit.point, debugrayend, Color.red);
    15.             Debug.Log(hit.point);
    16.             //Instantiate (particle, hit.point, transform.rotation); // Create a particle if hit
    17.         }
    18.     }
    19. }
    I changed alot over time, mainly to try and get the position to work.

    Can anyone give me an explanation as to why RaycastHit.point always returns 0,0,0?
     
  2. Raziaar

    Raziaar

    Joined:
    Dec 20, 2009
    Posts:
    82
    It's because you're using the wrong overload. And as such, your RaycastHit variable is never getting any information. Being a struct, all of its stuff is set to the variable defaults.

    Try this instead. notice that it's a different overload that includes the RaycastHit out parameter.


    Code (csharp):
    1.  if (Physics.Raycast (ray, out hit))
    2.       {
    3.          Debug.DrawLine (hit.point, debugrayend, Color.red);
    4.          Debug.Log(hit.point);
    5.          //Instantiate (particle, hit.point, transform.rotation); // Create a particle if hit
    6.       }

    Physics.Raycast has 11... that's right, eleven different method overloads so you can cast rays how you need to. The bolded one is the one you want. They all return a bool.


    Physics.Raycast(Ray ray);
    Physics.Raycast(Ray ray, float distance);
    Physics.Raycast(Ray ray, out RaycastHit hitInfo);
    Physics.Raycast(Vector3 origin, Vector3 direction);
    Physics.Raycast(Ray ray, float distance, int layerMask);
    Physics.Raycast(Ray ray, out RaycastHit hitInfo, float distance);
    Physics.Raycast(Vector3 origin, Vector3 direction, float distance);
    Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo);
    Physics.Raycast(Ray ray, out RaycastHit hitInfo, float distance, int layerMask);
    Physics.Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask);
    Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float distance);
    Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float distance, int layerMask);
     
    SweatyChair, NurIhsan and Nomenokes like this.
  3. Divine Rage

    Divine Rage

    Joined:
    Jan 10, 2010
    Posts:
    3
    Code (csharp):
    1. var particle : GameObject;
    2. var debugraystart : Vector3;
    3. var debugrayend : Vector3;
    4.  
    5. function Update ()
    6. {
    7. if (Input.GetButtonDown ("Fire1"))
    8. {
    9. var ray = Camera.main.ScreenPointToRay (Input.mousePosition); // Construct a ray from the current mouse coordinates
    10. var hit : RaycastHit;
    11.  
    12. //if (Physics.Raycast (ray))
    13. //{
    14. //Debug.DrawLine (hit.point, debugrayend, Color.red);
    15. //Debug.Log(hit.point);
    16. //Instantiate (particle, hit.point, transform.rotation); // Create a particle if hit
    17. //}
    18.  
    19.  if (Physics.Raycast (ray, out hit))
    20. {
    21. Debug.DrawLine (hit.point, debugrayend, Color.red);
    22. Debug.Log(hit.point);
    23. //Instantiate (particle, hit.point, transform.rotation); // Create a particle if hit
    24. }
    25.  
    26.  
    27. }
    28. }
    This is what I currently have, I commented out my original part, and used yours, as I believe I'm ment to. Seeing as your little snippet didn't have the ScreenPointToRay stuff and all.

    Anyway, this is giving me 3 errors;

    Assets/RayFromMousePosition.js(19,32): BCE0044: expecting ), found 'hit'.

    Assets/RayFromMousePosition.js(19,36): BCE0043: Unexpected token: ).

    Assets/RayFromMousePosition.js(21,51): BCE0044: expecting :, found ';'.

    I'm pretty new to Javascript/general scripting, and it's already giving me a headache... :?
     
  4. Raziaar

    Raziaar

    Joined:
    Dec 20, 2009
    Posts:
    82
    Hmm. The mistake is mine.

    See, I don't use javascript, I use C#.

    Apparently in javascript you don't have to specify "out", and in fact you cannot or it causes errors.

    Simply remove the "out" part... and it'll work. Like this.

    Physics.Raycast (ray, hit)


    My apologies... I didn't know how javascript treats out variables.
     
  5. Divine Rage

    Divine Rage

    Joined:
    Jan 10, 2010
    Posts:
    3
    Thanks, I've got it working now.
    Annoying how C# and Javascript can seem so similar.

    Anyway, I'll just post my current, working, Javascript code for 'future generations'. :D

    Code (csharp):
    1. var particle : GameObject;
    2.  
    3. function Update ()
    4. {
    5.     if (Input.GetButtonDown ("Fire1"))
    6.     {
    7.         var ray = Camera.main.ScreenPointToRay (Input.mousePosition); // Construct a ray from the current mouse coordinates
    8.         var hit : RaycastHit;
    9.  
    10.                  if (Physics.Raycast (ray, hit))
    11.          {
    12.             Debug.DrawLine (Camera.main.transform.position, hit.point, Color.red);
    13.             Debug.Log(hit.point);
    14.             //Instantiate (particle, hit.point, transform.rotation); // Create a particle if hit
    15.         }
    16.     }
    17. }
     
  6. Odysseus

    Odysseus

    Joined:
    Jun 19, 2009
    Posts:
    44
    Hey thanks for posting that final version of the script! Helped me with what I am doing right now. Thanks a million! :D
     
  7. Essal

    Essal

    Joined:
    Feb 16, 2010
    Posts:
    107
    Sorry if I am asking stupidly,
    but what If I want the ray to go from a 3rd person character to the mouse position, and also emit a particle at the point the ray hits a collider (if it does ofc)
     
  8. Flimgoblin

    Flimgoblin

    Joined:
    Nov 25, 2009
    Posts:
    89
    The mouse position only really works in 2d, so you need to cast your ray to find what you're clicking on (e.g. is it the terrain, or an object or nothing?)

    So you'd use something like the above to get your hit.point. Assuming it's something like a top-down RTS style control you'd maybe want to use a layer so you're only ever colliding with the terrain.

    You'd then use the transform.position of your 3rd person character and draw a ray from there to your hit point.

    rough example (this isn't tested code, just an outline):

    Code (csharp):
    1.  
    2.  
    3. var actor:GameObject; // your 3rd person character
    4. var particle : GameObject;
    5.  
    6. function Update ()
    7. {
    8.    if (Input.GetButtonDown ("Fire1"))
    9.    {
    10.       var mouseray = Camera.main.ScreenPointToRay (Input.mousePosition); // Construct a ray from the current mouse coordinates
    11.       var mousehit : RaycastHit;
    12.         // Note: might want to use a layer mask here, ignoring for simplicity for now
    13.      if (Physics.Raycast (mouseray, mousehit))
    14.        {
    15.           var direction=(mousehit.point-actor.transform.position);
    16.           var hit : RaycastHit;
    17.           var ray=new Ray(actor.transform.position, direction); // ray firing from the actor's location towards the point that the mouse click hits the terrain
    18.           Debug.DrawRay(ray,Color.red);
    19.  
    20.           if(actor.collider.Raycast(ray, hit)){
    21.              Instantiate (particle, hit.point, particle.transform.rotation);
    22.            }
    23.          
    24.       }
    25.    }
    26. }
    27.  
    28.  
    Now this will probably end up having your character fire bullets slightly down towards the ground, if you do something like:

    Code (csharp):
    1.  
    2. direction.y=0
    3.  
    (or possibly .z depending on which way your scene is rotated) your second raycast will always stay level, and will only hit things at the same height as your actor.
     
    Moondrakor likes this.
  9. Essal

    Essal

    Joined:
    Feb 16, 2010
    Posts:
    107
    Thanks for the explanation:)

    :)
    I'll try it out.
     
  10. Lemon223

    Lemon223

    Joined:
    Nov 28, 2010
    Posts:
    11
    Hello,

    i am making a RTS game and wanted to place buildings where i clicked with my mouse and later on select it to make units in it. so for the first task i found this topic and tried this script (after alot of other scripts) but everytime i've got the same error i realy don't know what it is and my teacher has the same he cant find it in my script. i am using the same script from this topic but it does'nt work.

    Code (csharp):
    1. var particle : GameObject;
    2.  
    3. function Update ()
    4. {
    5.     if (Input.GetButtonDown ("Fire1"))
    6.     {
    7.         var ray = Camera.main.ScreenPointToRay (Input.mousePosition); // Construct a ray from the current mouse coordinates
    8.         var hit : RaycastHit;
    9.  
    10.                  if (Physics.Raycast (ray, hit))
    11.          {
    12.             Debug.DrawLine (Camera.main.transform.position, hit.point, Color.red);
    13.             Debug.Log(hit.point);
    14.             //Instantiate (particle, hit.point, transform.rotation); // Create a particle if hit
    15.         }
    16.     }
    17. }
    i've added this script to my camera called "camera" not main camera i lost that camera or is that the problem? i deleted that main camera accidentally.

    the error what i get is :
    NullReferenceException
    UnityEngine.Camera.ScreenPointToRay (Vector3 position) (at E:/BuildAgent/work/71ca6fec1b41cc30/Runtime/Export/Generated/Graphics.cs:614)
    Build Object.Update () (at Assets/Scripts/Build Object.js:7)


    if i dubble click on the error it says it is in this line of the script :
    var ray = Camera.main.ScreenPointToRay (Input.mousePosition); // Construct a ray from the current mouse coordinates

    I am a beginning javascripter so it can be realy simple but it gives me a realy headache :(

    thanks in advance :) and sorry for my bad english,
     
    Rong08 likes this.
  11. Lemon223

    Lemon223

    Joined:
    Nov 28, 2010
    Posts:
    11
    i've tried again and again but i found the problem of the error in my unity my main camera is'nt tagged as "MainCamera" so it won't been seen in any scripts so if someone else get this you know now the problem ;). the script doesn't work completely for my game because the particle won't spawn at my mouse with transform position only the rotation works.

    Thanks for this script a good starting point!

    Lemon,
     
    cliffmlimwa likes this.
  12. gochmarr

    gochmarr

    Joined:
    Dec 27, 2012
    Posts:
    1