Unity 2D Raycast from mouse to screen

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.

	/// <summary>
	/// Cast a ray from the mouse to the target object
	/// Then sets the target position of the ability to that object.
	/// </summary>
	public void ScreenMouseRay()
	{
		Vector3 mousePosition = Input.mousePosition;
		mousePosition.z = Mathf.Infinity;

		//RaycastHit2D hit = Physics2D.Raycast(Input.mousePosition ,Vector2.zero,Mathf.Infinity); //Hit object that contains gameobject Information
		RaycastHit2D hit = Physics2D.Raycast(mousePosition, mousePosition - Camera.main.ScreenToWorldPoint(mousePosition),Mathf.Infinity);

		Debug.DrawRay(mousePosition, mousePosition - Camera.main.ScreenToWorldPoint(mousePosition),Color.blue);
		if(hit)
		{
			//Debug.Log("Ray has been Cast and hit an Object");
			targetPos = hit.collider.gameObject.transform.position; //Save the position of the object mouse was over
			Debug.Log ("Target Position: " + targetPos);

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.

  • 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.

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:

RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

if(hit.collider != null)
{
    Debug.Log ("Target Position: " + hit.collider.gameObject.transform.position);
}

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.

24 Likes

Thanks for the reply mrsquare I’ll have to give this a Shot when i get home.

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.

Here is the solution we came too.

	/// <summary>
	/// Cast a ray from the mouse to the target object
	/// Then sets the target position of the ability to that object.
	/// </summary>
	public void ScreenMouseRay()
	{
		Vector3 mousePosition = Input.mousePosition;
		mousePosition.z = 5f;

		Vector2 v = Camera.main.ScreenToWorldPoint(mousePosition);

		Collider2D[] col = Physics2D.OverlapPointAll(v);

		if(col.Length > 0){
			foreach(Collider2D c in col)
			{
				//Debug.Log("Collided with: " + c.collider2D.gameObject.name);
				targetPos = c.collider2D.gameObject.transform.position;
			}
		}
	}
1 Like

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.

16 Likes

Great tips MelvMay thanks a bunch!

This worked

1 Like

make sure your obj have collider2D, then it works to me:)

void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit2D rayHit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
            Debug.Log(rayHit.transform.name);

        }
    }
26 Likes

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.

2 Likes

Thanks

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.

1 Like

Collider2D rayHit = Physics2D.OverlapBox(Input.mousePosition, new Vector2(1, 1), 0);
if(rayHit)
Debug.Log(rayHit.transform.name);

This worked for me

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.

1 Like

Finally this worked for me :slight_smile: Thank you.

It’s been more than a month searching for a solution. I found here from your answer. It is solved finally :), thank you so much.