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:
A new version of the Inventory System is available. This version requires Godot Engine 4.3 and includes many refinements. New Drag and Drop system The Drag-and-Drop component has received a major overhaul. The previous system was quite complex and the separation of the classes that implemented the click-and-drag and click-and-release approaches had so much overlap …
The latest inventory system is now available and it focuses on multiplayer permissions. The new Access Manager component validates client requests to ensure players can’t cheat and interact with inventories they’re not supposed to be able to have access to. New features: Bug fixes:
A smaller update. The inventory components now have custom icons to make it easier to tell them apart. This release also includes additional bug fixes:
Creating network connections with Godot is simple — as long as you have the other party’s IP address, and there’s no NAT gateway involved. Unfortunately, that’s exactly the problem in most cases. You don’t know the other party’s IP, and these days, just about everyone is behind a combination wifi router/gateway/firewall with NAT. Conceptually, NAT …
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
Inventory System v1.16 available
A new version of the Inventory System is available. This version requires Godot Engine 4.3 and includes many refinements. New Drag and Drop system The Drag-and-Drop component has received a major overhaul. The previous system was quite complex and the separation of the classes that implemented the click-and-drag and click-and-release approaches had so much overlap …
Inventory System v1.11 available
The latest inventory system is now available and it focuses on multiplayer permissions. The new Access Manager component validates client requests to ensure players can’t cheat and interact with inventories they’re not supposed to be able to have access to. New features: Bug fixes:
Inventory System v1.4 available
A smaller update. The inventory components now have custom icons to make it easier to tell them apart. This release also includes additional bug fixes:
Creating a UDP peer-to-peer connection
Creating network connections with Godot is simple — as long as you have the other party’s IP address, and there’s no NAT gateway involved. Unfortunately, that’s exactly the problem in most cases. You don’t know the other party’s IP, and these days, just about everyone is behind a combination wifi router/gateway/firewall with NAT. Conceptually, NAT …