How we removed a major editor slowdown caused by duplicate viewport rendering and always-on editor updates.
Godot Version: 4.x
Area: 3D UI / Health Bar
Symptoms: Editor hangs or becomes very slow when scenes/health_bar_3d.tscn is present/instanced
The Problem
The editor became sluggish as soon as scenes/health_bar_3d.tscn was used.
Changing unrelated nodes could take a long time to reload.
At first glance, the scene looked simple. The issue was hidden in how it rendered:
- It contained two viewport-based health bar pipelines at the same time (one legacy, one active).
- The script ran as
@tool, so update logic executed in the editor continuously. - The viewport used
UPDATE_ALWAYS, forcing constant redraw even when nothing changed.
Combined, that created expensive editor-time work every frame.
Root Cause
scenes/health_bar_3d.tscn had two separate render chains:
Sprite3D/SubViewport/ProgressBar(legacy path)BillboardSprite/Viewport/UI/ProgressBar(active path used by script)
And scenes/health_bar_3d.gd had:
@tool(runs in editor)_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
That meant the scene was doing redundant viewport rendering and editor-time processing even when idle.
The Fix
1) Remove the duplicate legacy viewport path
In scenes/health_bar_3d.tscn, we removed:
Sprite3DSprite3D/SubViewportSprite3D/SubViewport/ProgressBar- related subresources (
ViewportTexture_8v4ab,CanvasItemMaterial_8v4ab)
Now the scene has one rendering path only:
BillboardSprite+Viewport+UI/ProgressBar
2) Stop continuous viewport redraws
In scenes/health_bar_3d.gd:
- Changed
UPDATE_ALWAYStoUPDATE_ONCE. - Added
_queue_viewport_redraw()and call it only when visuals change.
_viewport.render_target_update_mode = SubViewport.UPDATE_ONCE
func _queue_viewport_redraw() -> void:
if not _viewport:
return
_viewport.render_target_update_mode = SubViewport.UPDATE_ONCE
3) Disable editor-time script execution
In scenes/health_bar_3d.gd:
- Removed
@tool.
This prevents per-frame health bar behavior from running in the editor while you are editing scenes.
Files Changed
scenes/health_bar_3d.tscnscenes/health_bar_3d.gd
Why This Works
- One viewport pipeline instead of two cuts redundant rendering work.
UPDATE_ONCEredraws only when needed, not every frame.- Removing
@toolkeeps runtime behavior out of editor idle loops.
Together, these changes remove the main sources of editor stalls while keeping the in-game health bar functionality.
Practical Rule for Future Godot UI
If a UI element uses SubViewport:
- Keep a single render path.
- Prefer
UPDATE_ONCE(or disabled) overUPDATE_ALWAYS. - Use
@toolonly when editor-time behavior is truly required.
These three checks prevent most viewport-related editor slowdowns.
Leave a Reply