- Home /
2D - finding object at mouse position
I am building a 2D platformer (sort of). Default Unity setup, looking down the Z axis. I need to do two different things with detecting the mouse position.
1) Player can interact with the item he's pointing at with the mouse (both in world, and in UI). 2) A UI feature needs to show a tooltip when the mouse is over certain items.
All my objects in game world are at z = 0. My canvas was at z = -5, but I've moved that to 0 too now. My camera is at z = -10. My camera follows the player in X and Y axes.
I have tried three approaches to this:
Vector3 mousePosition = cam.ScreenToWorldPoint(Input.mousePosition);
mousePosition.z = -10;
RaycastHit2D hit2 = Physics2D.Raycast(cam.transform.position, mousePosition - cam.transform.position, 500, mouseInteract);
if (hit2.collider != null)
{
mouseObject = hit2.transform;
} else
{
mouseObject = null;
}
The "2D" approach assumes all co-ordinates are at z=0, so instead of casting a ray from the camera, it casts from the player (which is at the same X/Y, but at z=0). This means the player can only interact with the items closest to him (which might work, but it's not what I'm trying to do right now). It also never collides with anything in the UI layer. (the layerMask does include the UI layer).
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
{
//Debug.Log(hit.transform.gameObject.name);
mouseObject2 = hit.transform;
} else
{
mouseObject2 = null;
}
RaycastHit hit3;
if (Physics.Raycast(cam.transform.position, mousePosition - cam.transform.position, out hit3, 500, mouseInteract))
{
mouseObject3 = hit3.transform;
} else
{
mouseObject3 = null;
}
These two different 3D approaches never detect anything. Neither the UI nor the gameObjects in world.
I'm not sure if there's a way to use the 2D physics to do this, as Unity is still 3D, as much as it would like to think it isn't when you're in 2D mode. But I am totally at a loss as to why the 3D raycasts aren't picking up anything at all.
I have tried setting "mousePosition.z = -10;" to 0, 10, -10, 5, -5. None of those changed anything.
I'm sure someone is going to point out the obvious problem in less time than it took me to type all this...
Thanks in advance!
Well, I have made some progress. Swapping the BoxCollider2D on the 2D in-game objects for a BoxCollider allows them to be picked up by the 3D ray version of the logic. However, I also had to swap the RigidBody2D for a RigidBody too, and that means the objects now fall off the back of the game world, as they are free to move on the Z access.
Also, my player object no longer collides with these objects, as the player is only 2D, not 3D.
So I think this has to be a 2D solution, but I have no idea how to make that work. Please someone help! :)
I have made more progress. I realized by reversing the 2D raycast, I get the collision closest to the mouse, not the player. And by shortening the range, I don't get a collision if I move off the object. So I think my in-game objects issue is solved.
But I still have no idea how to get a collision with the UI elements. If I give them a Box Collider, I won't be able to walk through them, and that's definitely not the plan!
Still need help, just less of it than I thought!
Answer by RhinoPhyre · Mar 06, 2018 at 01:35 AM
Well, I solved it.
My 2D raycast solution was closest to a working solution. I had to reverse the Vector3s, so it was originating at the mouse and casting towards the player. This ensured it would hit the object the mouse was over first, and not the one closest to the player along that line. But when the mouse was over nothing, it would still hit the one closest to the mouse in that direction. So I had to shorten the range as well. Now that part works 100%
RaycastHit2D hit2 = Physics2D.Raycast(mousePosition, cam.transform.position - mousePosition , 0,001, mouseInteract);
The UI I had to do totally differently. I had to use Rect.Contains(Input.MousePosition), combined with an annoying variety of conversion functions to get the co-ordinates in the same systems. Neither 2D nor 3D raycasts would hit the UI elements.
This was a frustrating day with very little progress over all! :P
Answer by SadSwede · Mar 05, 2018 at 02:29 AM
Try Physics2D.Raycast
What should I do different from the first example in the question?
RaycastHit2D hit2 = Physics2D.Raycast(cam.transform.position, mousePosition - cam.transform.position, 500, mouseInteract);