Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CollisionObject2D._input_event() returns objects in a seemingly random order #38550

Closed
chepulis opened this issue May 7, 2020 · 5 comments
Closed

Comments

@chepulis
Copy link

chepulis commented May 7, 2020

Godot 3.2.1 GLES3
MacOs Catalina 10.15.4 (19E287), Mid 2015 Retina. AMD Radeon R9 M370X.

See, the docs state:

  1. If no one wanted the event so far, and a Camera is assigned to the Viewport, a ray to the physics world (in the ray direction from the click) will be cast. If this ray hits an object, it will call the CollisionObject._input_event()

Which i read as: in 2D Godot will respect z-index and canvas layers and give me things in front first, in the back last. Inverse of drawing order. After all, i'm in front of the glass, clicking/tapping on things. Reasonable, right?

image
(me, a beginner-ish, after a long time of banging my head against the wall)

What i'm getting, however, are three problems:

  • Godot is giving me nodes in the tree order, top-first
  • It also mixes them around a little, inconsistently between sessions on the same code
  • The docs are at the very least misleading

Maybe i'm missing something. I'm not too experienced, even after a year of Godotting. But at least some of that has to be a valid problem in need of fixing. Probably all three.

Video and reproduction
To reproduce, make many areas with various canvas layers and z-index and check print order.

Video of testing structure and the bugs: https://youtu.be/tD0x0wT9_jQ

Test project from the video:
InputOrder.zip

UPD: 3.2.2 beta2 yielded seemingly the same results
UPD2: To emphasize (after the renaming), i see the "tree order instead of reverse draw order" as a bug (as well as the occasional randomness). This might be a design decision, or a holdover from some ancient time when z-index and CanvasLayer.layer weren't a thing, but i think this form of input must take the draw order into consideration.

@Calinou Calinou changed the title CollisionObject2D._input_event() very broken CollisionObject2D._input_event() returns objects in a seemingly random oreder May 7, 2020
@Calinou Calinou changed the title CollisionObject2D._input_event() returns objects in a seemingly random oreder CollisionObject2D._input_event() returns objects in a seemingly random order May 7, 2020
@chepulis
Copy link
Author

chepulis commented Jun 5, 2020

Tested on the 3.2.2 Beta 4. Unsurprisingly, still present.
Possibly is also worth noting, that in my game build i observe this bug on Android as well.

Now, here's a detailed explanation for the people who don't want to watch the video.

There are five CanvasLayers, named in order, but with various CanvasLayer.layer values. Each has a set of the same five pickable Area2D instanced scenes, again named in order but with a various z-index. In 2D space they are all stacked on top of each other. At getting the _input_event they will print what CanvasLayer they're on, the .layer, their name and z-index:

image

We click them. We'd expect to see the "L:002:3 → 002 z:10" to be the first: it's the closest to us, it's drawn on top, that's what would be the real game target for the click. And the rest should adhere to the z-order, in case we need to, say, pick up multiple overlapping objects, or use the top object as a modifier (or ignore it in some cases). These are all my real world cases.

However, the one click (after the normal _input and _unhandled_input propagation) instead of doing the raycasting tries to propagate trough the tree top-first, in order. If we didn't need canvas and z-index (and we do), that would still be effectively going the opposite direction of the click.

image

The other issue is: the order stays consistent within the same launch, but not between multiple launches:

image

image

image

You can download this test project or watch the boring video in the post above.

Unless i manage to implement my own raycasting, i don't see an alternative to using pickable objects for my input. _gui_input has its own bug (that i will be reporting shortly) and wouldn't fit my needs anyway, while pickable objects are perfect (with the exception of being more broken than the american race relations and storefronts).

As this is a very important family of bugs for me, i'll keep testing and reporting here with every subsequent Godot release. I hope that's okay.

@LordBrkica
Copy link

Possibly related godotengine/godot-proposals#1058

@chepulis
Copy link
Author

@LordBrkica I'll post here, but it applies both here and in your thread.

IMHO, it seems to be only distantly related. I'm describing a set of 2D-specific issues where CollisionObject interaction in 2D has unexpected behavior and bugs as opposed to the same interaction in 3D.

And in fact, i'm using unhandled before CollisionObject2D. Unhandled is used to interact with objects that have been activated bound to a finger index, then the remaining input descends to new objects that can start interaction. This is important because otherwise objects would be unexpectedly dropped after the finger exists their shape, which is sometimes needed intentionally, sometimes just happens due to latency. And if unhandled was happening after, the lagging or overlapping objects would steal interaction.

I could, possibly, move it to regular input, i'm not sure if it will break anything else. Anyway, as it stands right this second, your proposal would break my stuff. But if it doesn't, then it adds versatility with input → CollisionObject → unhandled combo allowing for more complex interactivity.

Referring to your example, you have units be children of the map. I, too, have something comparable to unit/map setup, but the units aren't part of the map. In fact, the background interaction area is effectively under all the possible objects, so it gets interaction if no one is in front. It doesn't move itself, just passes relative movement to the camera. And it's on a separate CanvasLayer, and it would work perfectly if Godot wasn't using this tree-order priority and wasn't randomizing interaction order (everything described in this issue). You might be able to solve your problems the same way. Right now it works, but not every game start, which is a shame.

Perhaps i'm not understanding exactly the way you're using raycasting (i haven't tried implementing it yet) and will face the problems you're facing later down the road, when, if this issue isn't addressed before my release, i'll be forced to write my own raycasting. Perhaps, that's where your proposal becomes specifically relevant to me.

And thanks for digging up this issue, it needs to get some attention. And if we agree on anything, it's the fact that 2D interactions in Godot need work.

@LordBrkica
Copy link

I understand, I mean my problem is not really a bug and thats why I posted it in proposals.

Ideally, we could set a property (somewhere in the project or the editor) to define priority of unhandled_input vis-a-vis CollisionObject _inputevent and then get consistent behaviour.

You utilise the existing logic of unhandled_input being called before _input_event and thats ok.
I on the other hands see it like this:
Lets say you have a UI object say a Button. Clicking on a Button gets handeld before any unhandled inputs. And that makes sense, if you hovered the mouse over a button and clicked a button -> its probably button that interests you and not some stuff in background.

If you move your mouse over a CollisionObject (say a Spearman Unit standing on map) and click on it -> unhandled_input (of some Node in background) gets called sonner than the input_event of the your spearman. I find that counter intuitive so I created my post in godot proposals.

In any case - I hope you manage to find a fix or at least a workaround for your problem.

@pouleyKetchoupp
Copy link
Contributor

Closing as duplicate of #23051.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants