godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.97k stars 20.18k forks source link

Overlapping collision reports are non-deterministic when clicked despite sorting. #95493

Open Deledrius opened 1 month ago

Deledrius commented 1 month ago

Tested versions

System information

Windows 10 - Godot v4.3.rc3 - Vulkan (Forward+)

Issue description

Despite setting both set_physics_object_picking_sort and set_physics_object_picking_first_only as true, input events triggered when clicking an area with overlapped collision shapes produces a seemingly random picked shape.

Changing the node tree order or the z-index setting has no apparent effect on the outcome.

Steps to reproduce

As illustrated by the provided MRP, create two CollisionArea2D regions as children of an Area2D node. Assign any shape to both CollisionAreas, and place them so that they partially overlap. For the sake of telling them apart, the second is colored pink. Attach the following script to the Area2D, and then connect the input_event signal to the _on_input_event function.

extends Area2D

func _ready():
    get_viewport().set_physics_object_picking_sort(true)
    get_viewport().set_physics_object_picking_first_only(true)

func _on_input_event(viewport, event, shape_idx):
    if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
        var shape_owner = shape_owner_get_owner(shape_find_owner(shape_idx))
        print("Picking '%s'" % [shape_owner.name])

Important: Turn on "Visible Collision Shapes" in the Debug menu to see the shapes when running the MRP.

Clicking inside either the blue or pink CollisionShape2D regions alone works as expected. However, when clicking in the space where they overlap, the debug output in the provided GDScript shows that the shape_idx passed to the _on_input_event function can be either shape, and which shape it is changes with each click.

As both 'sort' and 'pick first' are enabled, it's expected that the "top" pink shape would be the only one sent to the _on_input_event function when the overlapped area is clicked.

Minimal reproduction project (MRP)

CollisionPickOrdering.zip

AThousandShips commented 1 month ago

Haven't studied the code specifically but the documentation seems to imply this is expected, it says (emphasis added):

If true, objects receive mouse picking events sorted

I'd say this means the objects receiving the input is sorted, and the object receiving the event is Area2D, not CollisionShape2D

Assuming this is correct it's a matter of documenting this more clearly

Deledrius commented 1 month ago

Indeed, it was unclear to me if this was expected or not after reading the documentation on this feature. If it is expected, then a fix would need to be requested in Godot Proposals, correct?

AThousandShips commented 1 month ago

Indeed, the first step would be to see if this is intentional or a bug, and if it's the former a proposal would be required for adding support for the shapes themselves!