Quick answer: The Godot editor typically runs with the Forward+ or Mobile renderer, which supports full GPU compute shaders. Most Android devices require the Compatibility renderer (OpenGL ES 3.0), which does not support GPU compute-based particles.
Here is how to fix Godot GPU particles not rendering mobile. Your particle effects look great in the editor and on desktop, but when you export to Android or iOS, the GPUParticles2D or GPUParticles3D nodes simply vanish. No errors in logcat, no warnings—just invisible particles. This is one of the most common mobile export issues in Godot 4, and it comes down to how GPU compute shaders interact with mobile rendering backends.
Why GPUParticles Disappear on Mobile Exports
GPUParticles2D and GPUParticles3D in Godot 4 rely on GPU compute shaders to simulate particle behavior. This works perfectly with the Forward+ and Mobile renderers, which use Vulkan or Metal under the hood. However, many mobile games export with the Compatibility renderer (OpenGL ES 3.0), which does not support compute shaders at all.
When GPUParticles encounter a renderer without compute support, they silently fail. No error is thrown, no warning is printed—the particles simply do not render. This catches developers off guard because everything works perfectly during desktop development.
The first thing to check is which renderer your export is using. Open Project > Project Settings > Rendering > Renderer and look at the mobile override. If it is set to gl_compatibility, GPUParticles will not work.
Solution 1: Switch to CPUParticles for Mobile
The most reliable fix is to replace GPUParticles with CPUParticles. CPUParticles2D and CPUParticles3D simulate particles on the CPU and work on every renderer, every platform, and every device.
Godot provides a built-in conversion tool. Select your GPUParticles node in the editor, click the Particles menu in the top toolbar, and choose Convert to CPUParticles2D (or 3D). This copies most of your particle configuration to a new CPUParticles node.
If you want to handle this in code at runtime, you can detect the renderer and swap nodes:
extends Node
@onready var gpu_particles := $GPUParticles2D
@onready var cpu_particles := $CPUParticles2D
func _ready() -> void:
var renderer := str(ProjectSettings.get_setting(
"rendering/renderer/rendering_method"))
if renderer == "gl_compatibility":
gpu_particles.visible = false
cpu_particles.visible = true
cpu_particles.emitting = true
else:
gpu_particles.visible = true
cpu_particles.visible = false
gpu_particles.emitting = true
Keep both versions in your scene and toggle visibility based on the active renderer. This gives you the best visual quality on capable hardware while maintaining compatibility everywhere else.
Solution 2: Use the Mobile Renderer with Vulkan
If your target devices support Vulkan (most Android devices from 2018 onward and all iOS devices with Metal), you can use the Mobile renderer instead of Compatibility. The Mobile renderer supports compute shaders and therefore GPUParticles.
To configure this, go to Project > Project Settings > Rendering > Renderer and set the mobile override to mobile instead of gl_compatibility. Be aware that this narrows your supported device range—older devices without Vulkan/Metal support will not be able to run your game.
You can check device support at runtime:
func supports_gpu_particles() -> bool:
var rd := RenderingServer.get_rendering_device()
return rd != null
If RenderingServer.get_rendering_device() returns null, the device is running on OpenGL ES and compute shaders are unavailable.
Solution 3: Fix ParticleProcessMaterial Settings for Mobile GPUs
Even when using a Vulkan-capable renderer on mobile, some GPUParticles configurations can fail on mobile GPUs due to hardware limitations. Common culprits include excessive particle counts, complex collision setups, and sub-emitters.
Keep these mobile GPU constraints in mind:
# Mobile-friendly particle settings
func configure_mobile_particles(particles: GPUParticles2D) -> void:
# Keep particle count reasonable (under 500 for mobile)
particles.amount = 200
# Avoid sub-emitters on mobile — they double GPU workload
particles.process_material.sub_emitter_mode = \
ParticleProcessMaterial.SUB_EMITTER_DISABLED
# Use simple collision or disable it
particles.process_material.collision_mode = \
ParticleProcessMaterial.COLLISION_DISABLED
# Reduce lifetime to keep active particle count low
particles.lifetime = 1.0
# Disable trails on mobile — they are expensive
particles.trail_enabled = false
Some mobile GPUs also struggle with the attractor and turbulence features on ParticleProcessMaterial. If particles render but cause severe frame drops, disable these features and test again.
Solution 4: Ensure the Process Material Is Assigned
A surprisingly common reason for invisible GPUParticles is a missing or null process_material. Without a ParticleProcessMaterial assigned, the node has no instructions for how to emit or move particles.
# Check if process material is set
func _ready() -> void:
var particles := $GPUParticles3D
if particles.process_material == null:
push_error("GPUParticles3D has no process material assigned")
var mat := ParticleProcessMaterial.new()
mat.direction = Vector3(0, 1, 0)
mat.initial_velocity_min = 2.0
mat.initial_velocity_max = 5.0
mat.gravity = Vector3(0, -9.8, 0)
particles.process_material = mat
Also verify that the draw_pass_1 mesh is assigned for GPUParticles3D. Without a mesh to render, the particles will simulate but remain invisible. For GPUParticles2D, check that the texture property is set.
Debugging Mobile Particle Issues
When particles are invisible on a mobile device, follow this diagnostic sequence:
1. Check the renderer. Run print(OS.get_current_rendering_method()) on device. If it prints gl_compatibility, GPUParticles will not work.
2. Verify the process material. A null process material means no emission. Check in the inspector or at runtime.
3. Confirm emitting is true. The emitting property defaults to true in the editor but may be set to false by scripts or animations.
4. Check visibility and draw order. Ensure the particles node is visible, not behind the camera, and not occluded by other geometry. For 2D, check the z-index.
5. Test with reduced particle count. Set amount to 10 and lifetime to 2.0 seconds. If particles appear with low counts but disappear at higher counts, you are hitting a mobile GPU memory or compute limit.
6. Examine logcat output. Connect your Android device via USB and run adb logcat | grep -i "godot\|vulkan\|opengl" to see if there are GPU-related warnings or errors.
“The safest approach for mobile particle effects in Godot 4 is to always have a CPUParticles fallback. Design your effects with CPUParticles first, then enhance with GPUParticles on capable devices. Your players on older phones will thank you.”
Related Issues
If you are troubleshooting other mobile export problems, see Fix: Godot HTTPRequest Not Completing or Timing Out for networking issues on mobile. For setting up automated bug reports from mobile players encountering rendering issues, check out How to Add a Bug Reporter to a Godot Game.
Mobile GPU limitations are the silent killer of particle effects. Always test on real hardware early in development, and keep a CPUParticles fallback in every scene that uses particle effects.