The Pause Handler: Working around Godot 4’s particle jitter bug
Godot Engine 4 has a bug (#50824) that causes particle jitter when the game is paused. It does look quite distracting.
The Bug in Action
This is a proof-of-concept wave shooter running in Godot Engine 4.0.2. Pausing the game was initially just a simple process_mode toggle. But as shown in the video clip above, there is a noticeable and quite distracting jitter for every particle effect that apparently stems from some interpolation issue.
To work around it, I wrote a small pause handler script that hides all the GPU particle effects:
class_nameGGPauseHandlerextends Node## The pause component allows you to toggle the game.#### While paused, it will hide particle effects to prevent visual jitter.## The issue is present in Godot 4 (tested until 4.0.2).#### @tutorial(Github Issue #50824: Particle jitter on low speed scale or when the SceneTree is paused due to interpolation): https://github.com/godotengine/godot/issues/50824signalpause_toggled(paused:bool)## The nodes' meta data field used to keep stateconstMETA_FIELD="gg_pause"## This game node will have its [member Node.process_mode] adjusted to pause the game@exportvar game:Node## The action name (in the [InputMap]) for pausing the game.@exportvar pause_action_name:String="pause"## Hides/unhides particles when toggling to prevent jitter@exportvar hide_particles:bool=truefunc_ready():assert(game isNode, "Must specify the node that will be paused")assert(InputMap.has_action(pause_action_name), "Please ensure the action '%s' is configured (Project Settings..., Input Map)"% pause_action_name)## Pragmatic way to listen to [InputEvent]s and check whether the pause key/button was pressedfunc_input(event:InputEvent):if event isInputEventKeyand event.is_action_pressed(pause_action_name):toggle_pause()## Toggle pausefunctoggle_pause():if game.process_mode==PROCESS_MODE_INHERIT:if hide_particles:_hide_particles() pause_toggled.emit(true) game.process_mode=PROCESS_MODE_DISABLEDelse:if hide_particles:_show_particles() pause_toggled.emit(false) game.process_mode=Node.PROCESS_MODE_INHERIT## Find and hide all GPUParticle2D effectsfunc_hide_particles():for node inget_tree().root.find_children("*","GPUParticles2D",true,false): node.set_meta(META_FIELD, node.visible) node.visible=false## Restore visibility of all previously hidden GPUParticle2D effectsfunc_show_particles():for node inget_tree().root.find_children("*","GPUParticles2D",true,false):if node.has_meta(META_FIELD): node.visible= node.get_meta(META_FIELD) node.remove_meta(META_FIELD)
Now when the game is paused, the jitter is hidden away from the player, making the experience much more pleasant. Once the bug is fixed, it’s easy to disable or remove the hiding logic. The result looks pretty good.
The
pause_toggled
signal allows other nodes to react to pausing as well, which I’m using to show/hide the UI accordingly.
The Workaround Applied
I’m only writing the code here. The assets used are:
The latest version includes a few new enhancements, and an experiment: The sequencer demo uses inventory instances to hold music notes, which can be played back. This was inspired by music trackers that were popular in the 90s, such as Scream Tracker and Impulse Tracker. The sequencer isn’t meant to be a production-ready digital audio …
We’re excited about this release, which includes a range of quality-of-life additions and refinements. Drag-and-drop support has been improved with a second strategy: Click-and-release: Simply clicking (and releasing) an item will pick it up. This leverages Godot’s force-drag functionality and approximates the drag-and-drop behavior that games like Valheim and Palworld use in their inventory items. …
In this 2018 GDC session, Spry Fox‘s Daniel Cook explains how to keep human beings from being treated as interchangeable, disposable, or abusable when designing multiplayer games. If you’re developing, or thinking about developing a multiplayer game, this is a great talk to better understand the challenges of designing multiplayer interactions that result in more …
It’s been a while, but it was worth the wait. The latest version of the Inventory System is now available, with a long list of features, improvements, fixes, and documentation. This time the focus is on multiplayer. Let’s cover the features first: Bug fixes:
The Pause Handler: Working around Godot 4’s particle jitter bug
Godot Engine 4 has a bug (#50824) that causes particle jitter when the game is paused. It does look quite distracting.
The Bug in Action
This is a proof-of-concept wave shooter running in Godot Engine 4.0.2. Pausing the game was initially just a simple process_mode toggle. But as shown in the video clip above, there is a noticeable and quite distracting jitter for every particle effect that apparently stems from some interpolation issue.
To work around it, I wrote a small pause handler script that hides all the GPU particle effects:
Now when the game is paused, the jitter is hidden away from the player, making the experience much more pleasant. Once the bug is fixed, it’s easy to disable or remove the hiding logic. The result looks pretty good.
The
pause_toggled
signal allows other nodes to react to pausing as well, which I’m using to show/hide the UI accordingly.The Workaround Applied
I’m only writing the code here. The assets used are:
The ship controls and wave transitions are loosely inspired by Galactix, a game released in 1993 (and set in the far-away future of 2019).
Related Posts
Inventory System v1.8 available
The latest version includes a few new enhancements, and an experiment: The sequencer demo uses inventory instances to hold music notes, which can be played back. This was inspired by music trackers that were popular in the 90s, such as Scream Tracker and Impulse Tracker. The sequencer isn’t meant to be a production-ready digital audio …
Inventory System v1.10 available
We’re excited about this release, which includes a range of quality-of-life additions and refinements. Drag-and-drop support has been improved with a second strategy: Click-and-release: Simply clicking (and releasing) an item will pick it up. This leverages Godot’s force-drag functionality and approximates the drag-and-drop behavior that games like Valheim and Palworld use in their inventory items. …
Design Patterns for Building Friendships
In this 2018 GDC session, Spry Fox‘s Daniel Cook explains how to keep human beings from being treated as interchangeable, disposable, or abusable when designing multiplayer games. If you’re developing, or thinking about developing a multiplayer game, this is a great talk to better understand the challenges of designing multiplayer interactions that result in more …
Inventory System v1.13 available
It’s been a while, but it was worth the wait. The latest version of the Inventory System is now available, with a long list of features, improvements, fixes, and documentation. This time the focus is on multiplayer. Let’s cover the features first: Bug fixes: