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. Unity 2022.2 is now available as the latest Tech release.
    Dismiss Notice
  3. We are making some changes to the DOTS forums.
    Dismiss Notice
  4. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Unity 2D Raycast from mouse to screen

Discussion in '2D' started by Sinron, Nov 18, 2013.

  1. Sinron

    Sinron

    Joined:
    Oct 12, 2012
    Posts:
    16
    So in 4.2 I had Screencast working where i could cast a ray from my mouse out into the scene and get an objects position if i hit it. NOW things have changed since I'm switching to Physics 2D because it's a 2D game. Come to find out old raycast don't work on 2D colliders and i cannot for the life of me figure out how I'm going to get the position of an object that my mouse is over when an event is triggered.

    I'm avoiding using OnMouseOver on objects because this is going to be a random thing that is controlled 100% by the player.
    Below is a sample of my code i'm attempting to use and it's not even close to working.

    Code (csharp):
    1.     /// <summary>
    2.     /// Cast a ray from the mouse to the target object
    3.     /// Then sets the target position of the ability to that object.
    4.     /// </summary>
    5.     public void ScreenMouseRay()
    6.     {
    7.         Vector3 mousePosition = Input.mousePosition;
    8.         mousePosition.z = Mathf.Infinity;
    9.  
    10.         //RaycastHit2D hit = Physics2D.Raycast(Input.mousePosition ,Vector2.zero,Mathf.Infinity); //Hit object that contains gameobject Information
    11.         RaycastHit2D hit = Physics2D.Raycast(mousePosition, mousePosition - Camera.main.ScreenToWorldPoint(mousePosition),Mathf.Infinity);
    12.  
    13.         Debug.DrawRay(mousePosition, mousePosition - Camera.main.ScreenToWorldPoint(mousePosition),Color.blue);
    14.         if(hit)
    15.         {
    16.             //Debug.Log("Ray has been Cast and hit an Object");
    17.             targetPos = hit.collider.gameObject.transform.position; //Save the position of the object mouse was over
    18.             Debug.Log ("Target Position: " + targetPos);
    19.        
    After i get a raycast from mouse to object my goal is to use the targets position as the end destination for a ray going from the player to that target.
     
  2. JohnGallet

    JohnGallet

    Joined:
    Sep 27, 2013
    Posts:
    16
    + 1 on this problem, I have the same problem here.

    It seems that to click on an object in 2D to select it for example is a lot more complicated than it should be!!!

    How I can click on the screen and get the tag of a gameObject for example. The old Camera.main.ScreenPointToRay(Input.mousePosition) is not working anymore with the new 2D physics.
     
  3. mrsquare

    mrsquare

    Joined:
    Oct 25, 2013
    Posts:
    281
    See this thread:

    http://forum.unity3d.com/threads/210960-Raycast-with-sprites

    But basically, if you just want to click the mouse directly on an object and have the raycast hit it, this should work:

    Code (csharp):
    1.  
    2. RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
    3.  
    4. if(hit.collider != null)
    5. {
    6.     Debug.Log ("Target Position: " + hit.collider.gameObject.transform.position);
    7. }
    8.  
    The Raycast point needs to be in world coordinates, and setting a distance vector of zero means that it will only intersect with the object immediately under the cursor.
     
    Last edited: Nov 18, 2013
  4. Sinron

    Sinron

    Joined:
    Oct 12, 2012
    Posts:
    16
    Thanks for the reply mrsquare I'll have to give this a Shot when i get home.
     
  5. Sinron

    Sinron

    Joined:
    Oct 12, 2012
    Posts:
    16
    So it seems this is always casting the ray from the camera straight down and since the camera follows the player that's all it hits. Essentially it doesn't seem to be taking the position of the mouse into consideration at all.
     
    Last edited: Nov 19, 2013
  6. Sinron

    Sinron

    Joined:
    Oct 12, 2012
    Posts:
    16
    Here is the solution we came too.

    Code (csharp):
    1.     /// <summary>
    2.     /// Cast a ray from the mouse to the target object
    3.     /// Then sets the target position of the ability to that object.
    4.     /// </summary>
    5.     public void ScreenMouseRay()
    6.     {
    7.         Vector3 mousePosition = Input.mousePosition;
    8.         mousePosition.z = 5f;
    9.  
    10.         Vector2 v = Camera.main.ScreenToWorldPoint(mousePosition);
    11.  
    12.         Collider2D[] col = Physics2D.OverlapPointAll(v);
    13.  
    14.         if(col.Length > 0){
    15.             foreach(Collider2D c in col)
    16.             {
    17.                 //Debug.Log("Collided with: " + c.collider2D.gameObject.name);
    18.                 targetPos = c.collider2D.gameObject.transform.position;
    19.             }
    20.         }
    21.     }
     
    pleasecomeagainn likes this.
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    8,664
    Raycast/Linecast for 2D take Vector2 not Vector3 because they operate along the X/Y plane only as it's 2D physics not 3D.

    There is however specialized calls that do take a Ray type for people that want to use 2D colliders in a pseudo 3D context. These calls are "GetRayIntersection", "GetRayIntersectionAll" and "GetRayIntersectionNonAlloc" and do what the say, find an intersection of a 3D ray on a 2D collider. Note that these calls will purposely return nothing if your ray is cast along the X/Y plane itself as 2D colliders are infinitely thin so you must always cast your ray along the Z axis at some angle.

    Internally what these calls do are project the ray start/end points into the Box 2D collider space, perform a standard line-cast in 2D space to find which 2D colliders are hit then calculate using back-projection where on those colliders the ray intersects given the transform Z of the GameObject. All returned colliders are sorted based upon the direction of the ray along the Z axis i.e. front-to-back or back-to-front. This will also calculate an appropriate hit normal.

    In other words, use the ray-intersection calls to find RaycastHit2D(s) in 3D space for 2D colliders.

    Hope this helps.
     
  8. Sinron

    Sinron

    Joined:
    Oct 12, 2012
    Posts:
    16
    Great tips MelvMay thanks a bunch!
     
  9. EmulatorsGaming

    EmulatorsGaming

    Joined:
    Mar 6, 2018
    Posts:
    1
    This worked
     
    XMIEmpty likes this.
  10. tsumikiHUANG

    tsumikiHUANG

    Joined:
    May 15, 2018
    Posts:
    2
    make sure your obj have collider2D, then it works to me:)

    Code (CSharp):
    1. void Update()
    2.     {
    3.         if (Input.GetMouseButtonDown(0))
    4.         {
    5.             RaycastHit2D rayHit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
    6.             Debug.Log(rayHit.transform.name);
    7.  
    8.         }
    9.     }
     
  11. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    118
    FWIW, I find it supremely odd, and frustrating, that the Unity API chooses to have all 18 versions of Physics.Raycast() returns a bool, but none of the 8 versions of Physics2D.Raycast() returns a bool.

    I think it would have been nice to be harmonious in this way.
     
    Mashimaro7 and andreyshade like this.
  12. mtgroup04

    mtgroup04

    Joined:
    Dec 24, 2020
    Posts:
    1
    Thanks
     
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    8,664
    For the record, to check for colliders under the mouse position, use Physics2D.OverlapPoint because this is 2D physics, not 3D physics. If you don't need specifically to deal with a pseudo 3D ray. OverlapPoint is much faster too.
     
    Arno_Bistel likes this.
  14. Talha113

    Talha113

    Joined:
    Apr 10, 2019
    Posts:
    7
    Collider2D rayHit = Physics2D.OverlapBox(Input.mousePosition, new Vector2(1, 1), 0);
    if(rayHit)
    Debug.Log(rayHit.transform.name);

    This worked for me
     
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    8,664
    Sorry to say but that's completely incorrect. Not only does this thread not relate to checking if a 1x1 box overlaps at the mouse position but "Input.mousePosition" is in screen-space so would need converting to world-space.

    As I said previously, OverlapPoint is how you'd do it in 2D.
     
  16. Second2None

    Second2None

    Joined:
    Jul 1, 2022
    Posts:
    1
    Finally this worked for me :) Thank you.