Dexter's log

Dexter's log

Fixing Godot splash screen gray flicker

I’m polishing my new game, Just Fly, which means I’ve been restarting it dozens of times a day. After a while, I got really tired of the gray flicker between the native Godot boot splash and my custom loading screen. I finally tracked down and fixed the root cause, without just masking the symptoms.

The gray flicker between Godot’s native boot splash and the first scene

TL;DR: Do NOT set modes on the DisplayServer (like fullscreen or V-Sync) in your main script’s _ready() function if the requested value is already the current one. Re-applying identical settings causes Godot to redraw the window with a clear frame.

The workarounds that didn’t work

In my previous game, I “fixed” this issue by force-rendering a frame in the main script’s _ready() using await get_tree().process_frame. In Just Fly, however, that only made the flicker worse. It was just masking the symptom rather than solving the real problem.

I turned to the community and asked for help on the Godot subreddit . Most replies suggested setting the default clear color to black instead of Godot’s default gray. But as I noted in my post, that doesn’t eliminate the flicker, it just makes the screen flash black instead of gray, which is still annoying.

The black clear color “fix” still flickers

Other suggestions pointed to scene loading speed, arguing that loading too many resources stalled the engine, forcing Godot to show an empty cleared frame. This didn’t seem right: synchronous loading on the main thread (like preload) blocks execution. While blocked, the application isn’t redrawing its window nor handling input, so it shouldn’t be swapping buffers on its own.

Finding the Root Cause

The transition used to be smooth, so I knew something in my recent setup was triggering the clear frame buffer swap.

After digging into it, I have found that the issue was caused by applying graphics settings during the game’s startup. Specifically, setting the fullscreen mode or V-Sync mode via DisplayServer causes Godot to redraw the window buffer – even when the requested mode is the same as the current one. There could be more settings on the DisplayServer tha cause this, so beware.

Because my startup script always applied the saved settings, it forced Godot to render an empty cleared frame and swap buffers before the first scene had finished rendering its first frame.

The Fix

The fix is straightforward: only update DisplayServer settings if the requested value differs from the current one.

Here is what my settings handlers look like now:

func set_fullscreen_enabled(enabled: bool) -> void:
	var requested_mode: DisplayServer.WindowMode = (
		DisplayServer.WINDOW_MODE_FULLSCREEN if enabled else DisplayServer.WINDOW_MODE_WINDOWED
	)
	# apply the mode only if different, otherwise the app will flicker with the clear color (gray by default)
	if DisplayServer.window_get_mode() != requested_mode:
		DisplayServer.window_set_mode(requested_mode)
func set_vsync_enabled(enabled: bool) -> void:
	var requested_mode: DisplayServer.VSyncMode = (
		DisplayServer.VSYNC_ENABLED if enabled else DisplayServer.VSYNC_DISABLED
	)
	# apply the mode only if different, otherwise the app will flicker with the clear color (gray by default)
	if DisplayServer.window_get_vsync_mode() != requested_mode:
		DisplayServer.window_set_vsync_mode(requested_mode)

The Result

With those redundant calls removed, the transition is now completely seamless and flicker-free. I even added a subtle fade-in for the labels:

Seamless, flicker-free transition between Godot’s boot splash and first scene

To prove that scene loading time wasn’t the issue, I tested adding an artificial delay in _ready() with OS.delay_msec(5000). Godot’s native boot splash simply stays on screen for an extra five seconds, with zero flicker before the main scene appears.

Peace of mind restored! :)

Just Fly on Steam

The game is still in early development, but it already has a Steam page . If you like what you see, feel free to wishlist it!