Sprite Mouse Down Action Not Triggering When Overlapping a Mesh

Hi everyone,

I’ve encountered an issue with sprite interactions when using BABYLON.SpriteManager. Specifically, the OnPickDownTrigger action for a sprite doesn’t execute as expected when the sprite overlaps with a mesh.

Actual Behavior

  • The OnPickDownTrigger action does not execute if the sprite overlaps with the mesh. However:
    • OnPointerOverTrigger and OnPointerOutTrigger work as expected.
    • The OnPickDownTrigger works as expected if the sprite is not overlapping the mesh.

It seems like the mesh is intercepting the mouse events, preventing the OnPickDownTrigger from firing on the sprite.

Questions

  1. Is this behavior expected?
  2. If not, is there a workaround that ensures both the sprite and the mesh can handle their respective mouse events independently?
  3. Could this be a bug in the event handling logic of Babylon.js?

Thanks in advance for your help!

Best regards,

cc @amoebachant

Hi @rikdelmar thanks for the detailed question! The intended behavior is that meshes take priority over sprites during pick operations. However, meshes opt out of pointer move pick operations by default because it can be costly. That’s why you see the sprite appear to get priority for pointer move but the mesh have priority for pointer down.

If you want your mesh to get pointer move events, you can set enablePointerMoveEvents to true for that mesh, or if you want all meshes to get pointer move events (this can be costly!), you can set constantlyUpdateMeshUnderPointer to true for the scene.

In this playground, you can see how either approach gives you the same result - the mesh gets priority for both pointer move and pointer down events:

If you don’t want the mesh to be picked at all, you can set isPickable to false for that mesh.

I hope that helps, thanks!

1 Like

I would have expected the pointerdown event to prioritize sprites first, as they are less expensive compared to meshes. However, it seems that, to handle mousedown events on sprites, I should adopt this approach:

scene.onPointerObservable.add((pointerInfo) => {
    switch (pointerInfo.type) {
        case BABYLON.PointerEventTypes.POINTERDOWN:
            const pickResult = scene.pick(scene.pointerX, scene.pointerY);

            // Check if a sprite was picked
            if (pickResult?.pickedSprite) {
                console.log("Sprite clicked:", pickResult.pickedSprite.name);
                // Handle sprite behavior here
            } else if (pickResult?.pickedMesh) {
                console.log("Mesh clicked:", pickResult.pickedMesh.name);
                // Handle mesh behavior here
            }
            break;
    }
});

…instead of using the ActionManager method, as in the following example:

spriteActionManager.registerAction(
    new BABYLON.ExecuteCodeAction(
        BABYLON.ActionManager.OnPickDownTrigger, 
        function (actionEvent) { 
            actionEvent.source.cellIndex = 2;
            console.log('Sprite clicked:', actionEvent.source);
        }
    )
);

The main difference is that the first approach allows me to explicitly check if the event is related to a sprite or a mesh and handle them accordingly. Additionally, it seems more flexible for complex scenes where prioritization or specific behaviors between sprites and meshes are required.

Thanks again for the support and clarification!

1 Like

You could change the scene._inputManager.mouseDownPredicate to respect sprites as well.