OnMouse not being called on sprites with a rigidbody 2D

As soon as I add it it stops working, it just doesn’t run until I remove it
Does anyone know what’s happening?

Check over in the docs. OnMouse only works with Colliders (3D), not Collider2D

I don’t think a Rigidbody2D and Collider (3D) can coexist.

Are you sure? I’m using a box collider 2D and OnMouse gets called fine until I add a rigidbody

I just read the docs man. :slight_smile:

EDIT: you’re right, it works with BoxCollider2D, and it also works with or without Rigidbody2D for me…

EDIT2: if the Rigidbody is set to NOT simulated then OnMouse events do not fire.

using UnityEngine;

// @kurtdeker
//
// To use this:
//
//    - make a sprite in scene
//    - add a BoxCollider to it
//    - drop this script on it
//    - press PLAY and start clickin'
//
// requirements: on active GameObject, must have 3D collider
//
// Updated 1/5/2023 - it seems to work on Collider2D as well!
//

public class OnMouseEventsDemo : MonoBehaviour
{
    void OnMouseUpAsButton()
    {
        Debug.Log( "UpAsButton " + name);
    }
    void OnMouseDown()
    {
        Debug.Log( "Down " + name);
    }
    void OnMouseUp()
    {
        Debug.Log( "Up " + name);
    }
    void OnMouseEnter()
    {
        Debug.Log( "Enter " + name);
    }
    void OnMouseExit()
    {
        Debug.Log( "Exit " + name);
    }
    void OnMouseOver()
    {
        // high spam - uncomment if you really want it
//        Debug.Log( "Over " + name);
    }
}
1 Like

So i tested it and OnMouse only gets called if both the collider and rigidbody are in the same gameobject, but if the script and collider are child of the rigidbody it no longer works, I have no idea why though

That seems consistent with the documentation. It’s not like EVERYBODY gets told that some random object had a mouse over it. It has to be that object.

This isn’t something 2D nor either physics system implement btw, it’s the Camera system code. For 2D it uses Physics2D.GetRayIntersection. I believe the doc team updated that doc to include the fact that it works on 2D too but that hasn’t landed yet.

A Rigidbody2D has no effect on detecting a collider so if there are special rules then it’s something in the Camera code but I don’t see why it’d make any difference.

So I took a look at the camera code and yes, on both 2D and 3D physics it returns the GameObject the Rigidbody(2D) is on if there is one but if not it returns the GameObject the Collider is on.

Here’s the camera code for 2D/3D:

GameObject* GetGameObjectForRaycastHit(const RaycastHit& hit)
{
    Collider* collider = PPtr<Collider>(hit.collider);
    if (!collider)
        return NULL;

    Rigidbody* body = collider->GetRigidbody();
    return (body) ? body->GetGameObjectPtr() : collider->GetGameObjectPtr();
}

GameObject* GetGameObjectForRaycastHit(const RaycastHit2D& hit)
{
    Collider2D* collider = PPtr<Collider2D>(hit.collider);
    if (!collider)
        return NULL;

    Rigidbody2D* body = collider->GetRigidbody();
    return body ? body->GetGameObjectPtr() : collider->GetGameObjectPtr();
}

I’m not sure I like that behaviour but I guess there’s a reason why it was preferred. If it were like physics callbacks, it’d allow two callbacks if these two components were not on the same GameObject.

That makes things a little clearer, thank you

Depending on what you’re trying to do, you might wanna put your own collider on it and do your own raycast check from the camera touch ray. You can actually ask for a specific collider, “Does this ray hit this collider?”

Here’s some more scribbled notes and links about this stuff:

Raycasting, colliders, planes, Plane, etc:

And there is also EventSystem.RaycastAll for raycasting in the UI / EventSystems context.

Raycasting in 2D:

That’s a lot of good info, thanks for sharing

1 Like

Yes, I agree with Kurt here. I would also consider using the more-correct-for-2D Physics2D.OverlapPoint which happens to be a lot quicker too.