Kokodoko
Kokodoko

Reputation: 28138

How replace OnMouseDown in Unity's new input system?

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?

Upvotes: 9

Views: 19190

Answers (4)

Zachary Brooks
Zachary Brooks

Reputation: 300

For me, it seems the answer lies in the context type:

InputAction.CallbackContext

The way I did it was using the context "canceled" property. When it is false, that means the mouse press just occurred. When it is true, that means the mouse press has been caneceled (and then indicating a OnMouseUp event).

It seems it has a few properties to make this fit other use cases, such as a duration indicating how long the button was down etc.

Upvotes: 0

Cerst
Cerst

Reputation: 11

You can also just use

Mouse.current.leftButton.wasPressedThisFrame

With a Raycast and a object with a collider in world space it would look like this:

RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        if (Physics.Raycast(ray, out hit) && hit.transform.name == "TargetObjName")
        {
print("PointerOnObj");
            if (Mouse.current.leftButton.wasPressedThisFrame)
            {
                print("clicked");
            }
        }

Upvotes: 1

Kolja
Kolja

Reputation: 2759

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");
    }
}

Upvotes: 14

Stephan van der Feest
Stephan van der Feest

Reputation: 431

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");
    }
 }

Upvotes: 4

Related Questions