Quick answer: In Godot 4, set_shader_param() was renamed to set_shader_parameter(). The old method name from Godot 3.x no longer exists. Update your code to use material.set_shader_parameter('uniform_name', value) instead of material.set_shader_param('uniform_name', value).
Here is how to fix Godot shader uniform not updating GDScript. You declared a uniform in your shader, set its value from GDScript, and nothing changes. The shader keeps using the default value no matter what you pass in. This is one of the most common migration issues when moving from Godot 3 to Godot 4, and it has two distinct causes: the renamed API method and shared material resources.
The Symptom
You have a shader with a uniform declaration and you try to set it from GDScript:
# Your shader declares this uniform
# uniform float dissolve_amount : hint_range(0.0, 1.0) = 0.0;
# Your GDScript tries to set it
material.set_shader_param("dissolve_amount", 0.5)
# Nothing happens. The dissolve_amount stays at 0.0.
You see one or more of these issues:
- Calling
set_shader_param()produces an error: “Invalid call. Nonexistent function ‘set_shader_param’ in base ‘ShaderMaterial’.” - The function call runs without error but the shader uniform does not change visually.
- Changing the uniform on one node unexpectedly changes it on every node that uses the same material.
- The uniform updates in the inspector when you type a value, but code-based changes are ignored.
What Causes This
Cause 1: Renamed API in Godot 4. In Godot 3.x, the method was called set_shader_param() and get_shader_param(). In Godot 4.x, these were renamed to set_shader_parameter() and get_shader_parameter(). The old method names no longer exist. If you are following a Godot 3 tutorial or migrating an existing project, this is the most likely cause.
Cause 2: Shared material resources. When you assign a material in the Godot editor, multiple nodes can reference the same ShaderMaterial resource. If you set a uniform value on one node’s material, it changes for all nodes sharing that material. Conversely, if you think you are setting a unique value but it keeps being overwritten, another node or script may be setting the same shared material’s uniform to a different value on the same frame.
Cause 3: Uniform name mismatch. Uniform names are case-sensitive and must match exactly. If your shader declares uniform float dissolve_Amount but your GDScript calls set_shader_parameter("dissolve_amount", ...), the parameter silently fails because the names do not match. Godot does not warn you about setting a non-existent uniform—it just does nothing.
The Fix
Step 1: Use the Godot 4 API. Replace all set_shader_param calls with set_shader_parameter:
extends Sprite2D
func _ready():
# WRONG (Godot 3 API - will error in Godot 4)
# material.set_shader_param("dissolve_amount", 0.5)
# CORRECT (Godot 4 API)
material.set_shader_parameter("dissolve_amount", 0.5)
func _process(delta):
# Animate the uniform over time
var t = fmod(Time.get_ticks_msec() / 1000.0, 2.0) / 2.0
material.set_shader_parameter("dissolve_amount", t)
Step 2: Make the material unique per instance. If you need different uniform values on different nodes that share the same scene or material resource, you must duplicate the material:
extends Sprite2D
func _ready():
# Duplicate the material so changes only affect this node
material = material.duplicate()
# Now this only affects this specific sprite
material.set_shader_parameter("dissolve_amount", 0.5)
Alternatively, you can set this in the editor: select the material resource in the inspector, click the resource dropdown, and enable Resource → Local to Scene. This automatically creates a unique copy of the material for each instance of the scene.
Step 3: Verify uniform names match exactly. Print the available parameters to debug name mismatches:
extends Sprite2D
func _ready():
var shader_mat = material as ShaderMaterial
if shader_mat and shader_mat.shader:
var params = shader_mat.shader.get_shader_uniform_list()
for param in params:
print("Uniform: ", param.name, " Type: ", param.type)
# Now set with the exact name from the output above
material.set_shader_parameter("dissolve_amount", 0.5)
Step 4: Complete example with a dissolve shader. Here is a full working dissolve effect with proper GDScript integration:
// dissolve.gdshader
shader_type canvas_item;
uniform float dissolve_amount : hint_range(0.0, 1.0) = 0.0;
uniform sampler2D noise_texture;
uniform vec4 edge_color : source_color = vec4(1.0, 0.5, 0.0, 1.0);
uniform float edge_width : hint_range(0.0, 0.2) = 0.05;
void fragment() {
vec4 tex = texture(TEXTURE, UV);
float noise = texture(noise_texture, UV).r;
float edge = smoothstep(
dissolve_amount - edge_width,
dissolve_amount,
noise
);
COLOR = mix(edge_color * tex.a, tex, edge);
COLOR.a *= step(dissolve_amount, noise + edge_width);
}
# dissolve_sprite.gd
extends Sprite2D
@export var dissolve_duration: float = 1.5
var dissolve_progress: float = 0.0
var is_dissolving: bool = false
func _ready():
# Make material unique so each instance dissolves independently
material = material.duplicate()
func start_dissolve():
is_dissolving = true
dissolve_progress = 0.0
func _process(delta):
if not is_dissolving:
return
dissolve_progress += delta / dissolve_duration
dissolve_progress = min(dissolve_progress, 1.0)
material.set_shader_parameter("dissolve_amount", dissolve_progress)
if dissolve_progress >= 1.0:
is_dissolving = false
queue_free()
Why This Works
The set_shader_parameter() method writes a value to the ShaderMaterial’s parameter override map. When the rendering server processes the draw call for that node, it reads these overrides and passes them to the GPU as uniform values. The rename from set_shader_param to set_shader_parameter was part of Godot 4’s API consistency cleanup—many abbreviated method names were expanded to their full forms.
The material uniqueness issue exists because Godot uses resource sharing by default for efficiency. When you assign a material in the editor, the scene file stores a reference to a single material resource. All instances of that scene share the same resource in memory, which means uniform changes propagate to every instance. Calling duplicate() creates a new resource in memory with its own parameter map, breaking the shared reference.
The resource_local_to_scene flag achieves the same thing as duplicate() but is handled automatically by the engine when instances are created. It is the preferred approach when you know at design time that each instance needs independent material parameters.
If you are migrating a Godot 3 project, search your codebase for “set_shader_param” and “get_shader_param” and replace them all. This is one of the most common migration breakages and affects every shader-using script in your project.
Related Issues
If the shader itself is not applying at all (not just the uniforms), the issue may be a shader type mismatch. See Fix: Godot Custom Shader Not Applying to Sprite2D for the canvas_item vs spatial shader type fix.
If you are working with screen-space effects and the coordinates seem wrong even though uniforms are updating correctly, see Fix: Godot Screen-Space Shader Coordinates Off or Inverted.
set_shader_param → set_shader_parameter. Duplicate for unique instances.