Raycasting in 2D

Hello everyone, it’s my first post here. I’m working on a topdown 2d game, and I need some help/insight on better ways to make my point-and-click work.

Right now my code looks like this:

public class MouseInputController : MonoBehaviour
{
    public LayerMask Floor;
    public bool Fire1;
    ObjectMover _mover;

    [SerializeField]
    Vector3 mouseInput;

    [SerializeField]
    float cameraDistance = 10.0f;

    void Awake()
    {
        _mover = GetComponent<ObjectMover>();
        if (_mover == null) Debug.LogError(gameObject.name + " is missing a mover script!");
    }

    void Update()
    {
        mouseInput = Camera.main.ScreenToWorldPoint(new Vector3(CrossPlatformInputManager.mousePosition.x, CrossPlatformInputManager.mousePosition.y, cameraDistance));
        Fire1 = CrossPlatformInputManager.GetButton("Fire1");

        if (Fire1)
        {
            var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast (ray, out hit, 10000f, Floor)) _mover.setDestinationInput (mouseInput);
            }
        }
    }
}

The problem is it doesn’t work.

Previously I didn’t use raycast to check if I clicked on “Floor” or not, just sent raw mouse input to script that moves object. But I want to limit it’s movement to “arena” I have and allow for GUI interactivity (and without checking if I clicked on “arena” or not it will lead to problems).

For 2D raycasts you need to use Physics2D.Raycast

Ok, found a way to do it properly:

RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint (Input.mousePosition), Vector2.zero); //reuse it for clicking buttons and stuff
            if ((hit.collider != null)&&(hit.transform.tag.Equals("Arena"))) {
                Debug.Log("Hit something: " + hit.transform.tag);
                _mover.setDestinationInput (mouseInput);
            }

EDIT: fixed wording :stuck_out_tongue:

That’s not a workaround, that’s how you’re supposed to do it. You were using 3D physics queries previous. :wink:

BTW: RaycastHit2D has an implicit bool operator so you can do ‘if (hit) xxx’

Cool, thanks :slight_smile: Still getting used to Unity programming and figuring out how things work :slight_smile:

I have a new problem now though, and it’s weird (as I’m pretty sure it was working as intended before). Here is new code:

void Update()
    {
        if (gm.paused || gm.isBlocking || gm.isResting || !gm.playerTurn || mover.isMoving || gm.stamina <= 0) return;
        mouseInput = Camera.main.ScreenToWorldPoint(new Vector3(CrossPlatformInputManager.mousePosition.x, CrossPlatformInputManager.mousePosition.y, cameraDistance));
        Fire1 = CrossPlatformInputManager.GetButton("Fire1");

        if (Fire1)
        {
          
//RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint (CrossPlatformInputManager.mousePosition), Vector2.zero);
            //RaycastHit2D hit = Physics2D.Raycast(mouseInput, Vector2.zero);
            RaycastHit2D hit = Physics2D.Raycast(mouseInput+new Vector3(0,0,10), Camera.main.ScreenToWorldPoint (CrossPlatformInputManager.mousePosition));
            //RaycastHit2D hit = Physics2D.Raycast(mouseInput, Camera.main.ScreenToWorldPoint (CrossPlatformInputManager.mousePosition));
            Debug.Log (mouseInput+new Vector3(0,0,10));
            Debug.Log (Camera.main.ScreenToWorldPoint (CrossPlatformInputManager.mousePosition));

            if (!hit) {
                //Debug.Log ("Hit nothing");
                return;
            }
            switch (hit.transform.tag.ToString())
            {
            case "Arena":
                //Debug.Log("Hit something: " + hit.transform.tag);
                mover.setDestinationInput (mouseInput);
                break;
            case "Boss":
                Debug.Log ("Hit Boss! " + hit.transform.tag);
                break;
            default:
                Debug.Log ("Hit Unknown");
                break;
            }
        }
    }

It is supposed to move player if user clicks on any spot on Arena tagged object (works), do nothing if player clicks buttons or outside arena (works), do nothing (for now) when player clicks on boss (was working, now broken), do nothing if player clicks any object other than Boss or Arena (used to work, now broken too). I just can’t really see where is the problem…

Ok, somewhat fixed it.

void Update()
    {
        if (gm.paused || gm.isBlocking || gm.isResting || !gm.playerTurn || mover.isMoving || gm.stamina <= 0) return;
        Ray ray = Camera.main.ScreenPointToRay(CrossPlatformInputManager.mousePosition);
        mouseInput = new Vector3 (ray.origin.x, ray.origin.y, transform.position.z);
        Fire1 = CrossPlatformInputManager.GetButton("Fire1");

        if (Fire1)
        {
            RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);

            if (!hit) {
                //Debug.Log ("Hit nothing");
                return;
            }

            switch (hit.transform.tag.ToString())
            {
            case "Boss":
                Debug.Log ("Hit Boss! " + hit.transform.tag);
                break;
            case "Arena":
                //Debug.Log("Hit something: " + hit.transform.tag);
                mover.setDestinationInput (mouseInput);
                break;
            default:
                Debug.Log ("Hit Unknown");
                break;
            }
        }
    }

The issue was that all objects were in same plane (0 on Z axis) and while it was fine before, it stopped being fine now. I moved all objects by 1 unit from arena on Z axis and now it works again. Also improved code a bit.