How replace OnMouseDown in Unity's new input system?

Viewed 8453

Unity has a new inputsystem where the old OnMouseDown() {} no longer works.

In the migration guide they mention replacing this with Mouse.current.leftButton.isPressed. And in other forum posts they mention using an InputAction. The problem is that these options detect mouse clicks anywhere in the scene, instead of just on the object:

public InputAction clickAction;

void Awake() {
      clickAction.performed += ctx => OnClickedTest();
}

void OnClickedTest(){
      Debug.Log("You clicked anywhere on the screen!");
}

// this doesn't work anymore in the new system
void OnMouseDown(){
      Debug.Log("You clicked on this specific object!");
}

How can I detect mouse clicks on a specific gameObject with the new input system in Unity?

2 Answers

With this code somewhere in your scene:

using UnityEngine.InputSystem;
using UnityEngine;

public class MouseClicks : MonoBehaviour
{
    [SerializeField]
    private Camera gameCamera; 
    private InputAction click;

    void Awake() 
    {
        click = new InputAction(binding: "<Mouse>/leftButton");
        click.performed += ctx => {
            RaycastHit hit; 
            Vector3 coor = Mouse.current.position.ReadValue();
            if (Physics.Raycast(gameCamera.ScreenPointToRay(coor), out hit)) 
            {
                hit.collider.GetComponent<IClickable>()?.OnClick();
            }
        };
        click.Enable();
    }
}

You can add an IClickable Interface to all GameObjects that want to respond to clicks:

public interface IClickable
{
    void OnClick();
}

and

using UnityEngine;

public class ClickableObject : MonoBehaviour, IClickable
{
    public void OnClick() 
    {
        Debug.Log("somebody clicked me");
    }
}

Make sure you have a an EventSystem with an InputSystemUIInputModule in the scene and a PhysicsRaycaster or Physics2DRaycaster on your Camera, and then use the IPointerClickHandler interface on the object with a collider on itself or its children:

 using UnityEngine;
 using UnityEngine.EventSystems;
 public class MyClass : MonoBehaviour, IPointerClickHandler {
    public void OnPointerClick (PointerEventData eventData)
    {
        Debug.Log ("clicked");
    }
 }
Related