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:
Development snapshot #4 of Godot Engine 4.1 is here. Among many other changes, it fixes a lighting issue related to using Light-only mode in CanvasItemMaterial (#44559). Unfortunately, it also introduced a UX issue with gradient color pickers (#77745), which makes it quite difficult to work with gradients at all. If you use gradients, I recommend …
This release finally uses Godot Engine 4.4. It adds the GGCraftingSystem singleton and updates the GGInteractable2DStrategyCrafting class to use it. The crafting editor nodes now have prefixes, which makes it much easier to search for specific recipe or item nodes in larger crafting libraries. Some syntactic sugar was added as well. You can now easily …
A new version of the Inventory System is available. This release includes various refinements to existing systems to flesh out more combat-related functionality. Inventory Ammo Provider The GGAmmoProvider component is responsible for providing ammunition to equipped weapons. Previously, it only had a “simple” strategy: Creating ammunition out of thin air. The new GGAmmoProviderInventoryStrategy pulls ammunition …
Right after I got my Steam Deck, I wanted to know how hard it is to get a Godot game running on it. What’s the developer experience for someone who’s stepping through this for the first time? It was really easy to do, so I’m sharing this here, whether you’re following along or like to …
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_toggledsignal 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
Godot Engine 4.1.dev4 is available
Development snapshot #4 of Godot Engine 4.1 is here. Among many other changes, it fixes a lighting issue related to using Light-only mode in CanvasItemMaterial (#44559). Unfortunately, it also introduced a UX issue with gradient color pickers (#77745), which makes it quite difficult to work with gradients at all. If you use gradients, I recommend …
Inventory System 2 Alpha 4 available
This release finally uses Godot Engine 4.4. It adds the GGCraftingSystem singleton and updates the GGInteractable2DStrategyCrafting class to use it. The crafting editor nodes now have prefixes, which makes it much easier to search for specific recipe or item nodes in larger crafting libraries. Some syntactic sugar was added as well. You can now easily …
Inventory System v1.17 available
A new version of the Inventory System is available. This release includes various refinements to existing systems to flesh out more combat-related functionality. Inventory Ammo Provider The GGAmmoProvider component is responsible for providing ammunition to equipped weapons. Previously, it only had a “simple” strategy: Creating ammunition out of thin air. The new GGAmmoProviderInventoryStrategy pulls ammunition …
Running Godot Games on Steam Deck
Right after I got my Steam Deck, I wanted to know how hard it is to get a Godot game running on it. What’s the developer experience for someone who’s stepping through this for the first time? It was really easy to do, so I’m sharing this here, whether you’re following along or like to …