tl;dr: Last week I implemented most of the logic for meteor-blocking barriers, and I worked through a bizarre bug with inconsistent touch-event sequencing. Alas, it was another short week for me!
What happened last week?
Highlights
- I implemented most of the logic for meteor-blocking barriers.
- I debugged and found a work-around for a bizarre bug involving touch events triggering inconsistently (on some machines!).
Laundry list
- Barriers:
- Decouple selection, control, health, and highlight logic from the Station class so it can be shared by the new BarrierPylon class.
- Create command definitions and art for barrier-pylon-creation, barrier-pylon-move, barrier-connect, barrier-disconnect.
- Start adding logic for selecting barrier-pylon placements and triggering build commands.
- Enable overriding the PlayerTouchListener class.
- Cancel the normal implicit-player-navigation command when triggering an explicit barrier-pylon-build command.
- Update command logic to support non-station-based commands.
- Add support for creating and recycling barrier-pylons.
- Add support for disabling barrier-pylon-activation when there isn't more than one pylon.
- Add barrier-activation status to the info-panel.
- Add new CommandTypes for barrier-pylon recycling and info.
- Hook-up most of the plumbing for barrier-pylon radial-menu buttons.
- Hook-up the barrier-energy animation.
- Add support for tracking barrier-pylon health and destroying them when depleted.
- Add support for destroying meteors when colliding with barrier pylons or energy.
- Polish the barrier-energy animation.
- Randomize barrier-energy start frame.
- Miscellaneous:
- Automatically limit the window size to the monitor's size.
- Force LevelControlPressController to use consistent event sequencing by using a separate LevelControl to capture all events within the viewport, and then only trigger digests from this control using the CollisionObject2D.input_event API.
- Update LevelTouchListener to only process unhandled events after LevelControlPressController runs a digest.
The barrier bot doing his thing. |
A bizarre bug involving touch events triggering inconsistently
- I ran into a bizarre issue involving touch events triggering inconsistently.
- I still don't fully understand why the engine was behaving the way I was seeing.
- So I wanted to document it here, in case something similar comes up again.
- Background:
- I have a complex system for tracking touch events both globally and within the bounds of individual interactable regions within the level.
- Sometimes I want to treat a global touch event differently depending on whether it also occurred within the bounds of one of the interactable regions.
- However, Godot’s event sequencing causes the region-intersected touch events to happen later than the global touch events.
- I previously had been relying on Godot’s `call_deferred` API to reconcile this difference between the two different event systems.
- `call_deferred` lets you schedule a callback to run at the end of the current frame.
- This meant that I could digest all events from either source in one consolidated place per frame, and I could assume that all event sources had resolved by then.
- Specifically, Godot’s `CollisionObject2D.input_event` API is processed much later than the `Node._input` API for the same event.
- https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-input
- https://docs.godotengine.org/en/stable/classes/class_collisionobject2d.html#class-collisionobject2d-method-input-event
- The problem:
- The problem is that I started seeing these events happening with inconsistent sequencing!
- I used to consistently see events happening with the following sequence:
- Global event 1
- Local event 1
- Digest
- Global event 2
- Local event 2
- Digest
- ...
- However, I started seeing events sometimes happening with an extra digest after the global event and before the corresponding local event, so it would look like this.
- Global event 1
- Digest # Bad!
- Local event 1
- Digest
- Global event 2
- Local event 2
- Digest # Good!
- Global event 3
- Digest # Bad!
- Local event 3
- Digest
- ...
- Also, for whatever reason, I only started noticing this when I switched to using my laptop.
- This seems to indicate that either Godot sometimes processes `CollisionObject2D.input_event` on the frame after the touch occurs, or Godot sometimes triggers `call_deferred` at a different time in a frame’s lifecycle.
- I assume neither of these are intended!
- The solution:
- I forced my system to use consistent event sequencing by using a separate LevelControl to capture all events within the viewport, and then only trigger digests from this control using the CollisionObject2D.input_event API.
What's next?
- My last week of sabbatical before going back to a real job!
- Review my backlogs, and try to put any significant lingering framework issues into a somewhat stable state!
🎉 Cheers!
Comments
Post a Comment