Search Unity

How to Do Mouse Picking

Discussion in 'Scripting' started by gibberingmouther, Sep 21, 2017.

  1. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    Here's my code:
    Code (csharp):
    1.  
    2. void CastRay()
    3.         {
    4.             Vector3 mousePos = Input.mousePosition;
    5.             Vector3 enemyDepth = new Vector3(0, 0, -10);
    6.             //RaycastHit hit = Physics.Raycast(, Vector3.back, 100, 0);
    7.             RaycastHit hit;
    8.             Physics.Raycast(Camera.main.ScreenToWorldPoint(mousePos), Vector3.back, out hit, 100);
    9.             if (collider2d != null && collider2d.tag == "Enemy")
    10.             {
    11.                 //Debug.Log("enemy_over");
    12.                 enemy_over = true;
    13.             }
    14.             else enemy_over = false;
    15.         }
    16.  
    I had this working in 2D, but to get this to work right I have to do it in 3d. The idea is just to see if the mouse is over the enemy but it's not working. The editor says hit.collider etc. is deprecated so I declared a public Collider2D object collider2d instead. But it doesn't work.
     
  2. Rob21894

    Rob21894

    Joined:
    Nov 21, 2013
    Posts:
    309
    If youre making a 3D game you use use 3D physics so use Collider instead of Collider2D, also your physics.raycast is not in an if statement? Is this even running? Sorry never seen it done like this before
     
    gibberingmouther likes this.
  3. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    i'm making a 2d game but using a 3d raycast to see what's under the mouse (i.e. is the enemy under the mouse?). you're right that i just replaced hit witch collider without connecting collider to physics.raycast. not sure what i should do.
     
  4. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    There's a couple of ways to do it. The simple way is with OnMouseEnter.

    Another way is just raycasting from where the mouse cursor is into the world.

    Code (CSharp):
    1.     // Layer that enemy is on - remember to set this in inspector.
    2.     public LayerMask _layerMask;
    3.  
    4.     // Distance to cast ray
    5.     public float _raycastDistance = 10000f;
    6.  
    7.     void Update()
    8.     {
    9.         LogHoveredEnemyName();
    10.     }
    11.  
    12.     void LogHoveredEnemyName()
    13.     {
    14.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // Create ray from camera into the world through the mouse cursor position.
    15.  
    16.         RaycastHit hitInfo; // Empty var to store info about the thing we hit
    17.  
    18.         if (Physics.Raycast(ray.origin, ray.direction, out hitInfo, _raycastDistance, _layerMask)) // If raycast hit a collider...
    19.         {
    20.             if (hitInfo.collider.tag == "Enemy") // Tag is enemy?
    21.             {
    22.                 Debug.Log(hitInfo.collider.name); // Print name of enemy it hit.
    23.             }
    24.         }
    25.         else
    26.         {
    27.             // Not hitting anything
    28.         }
    29.     }
     
    gibberingmouther likes this.
  5. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    so if i wanted to use OnMouseEnter, i would put that in the enemy's attached script and then use an event to signal the hero's enemy_over script? i just learned about events (i guess i knew about them in java, but that was a long time ago).
     
  6. Rob21894

    Rob21894

    Joined:
    Nov 21, 2013
    Posts:
    309
    you do not need to use a 3D raycast if doing this. you can use something like;


    Code (CSharp):
    1.  
    2. void CastRay()
    3. {
    4.       RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
    5.  
    6.         if (hit.collider != null)
    7.         {
    8.             if (hit.collider.tag == "Enemy")
    9.             {
    10.                 Debug.Log(hit.collider.gameObject.name);
    11.  
    12.             }
    13.  
    14.         }
    15. }
    then run CastRay in a FixedUpdate or Update Loop
     
    Rem777 likes this.
  7. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    edit: could this be the reason -
    "Property collider has been deprecated. Use GetComponent<Collider>() instead"

    what should i do instead then?

    still not working:
    Code (csharp):
    1.  
    2. void CastRay()
    3.         {
    4.             //Vector3 mousePos = Input.mousePosition;
    5.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // Create ray from camera into the world through the mouse cursor position.
    6.  
    7.             RaycastHit hitInfo; // Empty var to store info about the thing we hit
    8.  
    9.             if (Physics.Raycast(ray.origin, ray.direction, out hitInfo, 100)) // If raycast hit a collider...
    10.             {
    11.                 if (hitInfo.collider.tag == "Enemy") // Tag is enemy?
    12.                 {
    13.                     Debug.Log(hitInfo.collider.name); // Print name of enemy it hit.
    14.                     enemy_over = true;
    15.                 }
    16.             }
    17.             else
    18.             {
    19.                 // Not hitting anything
    20.                 enemy_over = false;
    21.             }
    22.         }
    23.  
    enemy_over is not being triggered even when i click on the enemy. odd.
     
    Last edited: Sep 21, 2017
  8. Rob21894

    Rob21894

    Joined:
    Nov 21, 2013
    Posts:
    309
    Do the Enemys have a Collider2D on them?
     
  9. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    yes, a polygon collider. your code seems to work, though i'm still having an issue with the range being off and i can't figure out why.
     
  10. Rob21894

    Rob21894

    Joined:
    Nov 21, 2013
    Posts:
    309
    Can you supply a screenshot of your scene ? Also, is the polygon collider centered for your enemy?
     
  11. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    i fixed it by putting != null in with the nested if statement. the range is still off though, and i can't figure out why. it's always something.

    thanks guys!
     
  12. Rob21894

    Rob21894

    Joined:
    Nov 21, 2013
    Posts:
    309
    This is because if the hit.collider !=/not equal to null then it wont run the code, you can place it here instead;
    Code (CSharp):
    1.     void CastRay()
    2.     {
    3.         RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
    4.  
    5.         if (hit.collider != null)
    6.         {
    7.             if (hit.collider.tag == "Enemy")
    8.             {
    9.                 Debug.Log(hit.collider.gameObject.name);
    10.                 enemy_over = true;
    11.             }
    12.         }
    13.         else
    14.         {
    15.             enemy_over = false;
    16.             Debug.Log("enemyovernot");
    17.         }
    18.     }
     
    gibberingmouther likes this.
  13. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    My code was for 3D. I didn't see you needed 2D.

    Yes. You'd need to have a script on every enemy with OnMouseEnter inside it, then send a static event. The script that is interested in that data would subscribe to it in OnEnable and unsubscribe in OnDisable.
     
    gibberingmouther likes this.