Pausing both shaders and particles

Godot Version

4.3

Question

I’m attempting to pause all gameplay, including shaders and GPUparticles3d that both use TIME, the built in variable.

The problem is that just using get_tree.paused() does not affect shaders. So, I tried using Engine.time_scale = 0.0, but this causes the particles to stutter.

Any suggestions are welcome, and thank you.

Actually, when i pause the tree the GPUPaticles slowed down or somewhat … but it doesn’t look right. I would assume this is a bug, therefore a bug report seems to be appropriate.

1 Like

You can set a particle system’s speed scale to zero (0) to have it ‘stop’.

For a shader, it depends and ideally, you’d have a uniform to control how/what the shader does; e.g. I have a unit highlight that has a frequency value; setting this to have a value of zero ‘pauses’ the shader.

1 Like

Use a global uniform so you don’t need to set it for each shader

1 Like

wish i could add 3 solution check marks.

I tried setting frequency to 0, for the shader, which kind of worked. However, this reset the time in my shader, creating some visual disparity. I ended up creating a new “shader_time” var(in my singleton process) and updating it += delta, when the game is unpaused. When the game pauses, it stops increasing. This worked better for me than trying to update a shader global.

My shader is applied to certain meshes that are instanced. So, I added them to a global group, so my game manager singleton can access them and pass “shader_time” to the ShaderMaterial on nodes in this group.

GameManager singleton code below, (states control pausing)

func _process(delta: float) -> void:
	if get_tree().paused == false:  
		shader_time += delta
	set_shader_time(shader_time)

func set_shader_time(value : float):
	var group_nodes = get_tree().get_nodes_in_group("shader_nodes")
	for node in group_nodes:
		if node is MeshInstance3D:
			var material = node.material_overlay
			if material is ShaderMaterial:
				material.set_shader_parameter("shader_time", value)

2 Likes

here’s my pausing code for more context

Basically, I still use get_tree.paused(), which works for particles and gameplay.
I am now using a custom shader_time to halt shader effects.

func pause_game():
	get_tree().paused = true
	pause_menu_instance = pause_menu_scene.instantiate()
	get_tree().root.add_child(pause_menu_instance)
	current_game_state = GameState.PAUSE_MENU