Learn / Guides /

Why Ren'Py GUI files appear unused — but deleting them breaks your game

March 2026 4 min read Asset Management
Ren'Py Asset scanning gui/ Safe cleanup

If you've ever run an asset scanner on a Ren'Py project, you've probably seen this: dozens of files in game/gui/ flagged as unreferenced. They don't appear in script.rpy or any other .rpy file. A naive scanner treats them as dead weight.

Deleting them silently breaks your game's interface. Here's why.

How Ren'Py loads GUI files

Standard Ren'Py projects load their interface through gui.rpy — a generated file that ships with every new project. That file contains hundreds of variable assignments like these:

## The images used for the main and game menus. define gui.main_menu_background = "gui/main_menu.png" define gui.game_menu_background = "gui/game_menu.png" ## The image used for the window background. define gui.window_background = Transform("gui/window.png", xsize=gui.width) ## Buttons define gui.button_image = "gui/button/idle.png" define gui.button_hover_image = "gui/button/hover.png"

None of these assignments are image statements. None use show or scene. A scanner that looks for those keywords will never find gui/window.png, gui/main_menu.png, or any of the dozens of other paths assigned through gui.* variables.

The engine reads gui.rpy at startup and loads those images directly. Your script is never involved.

The core problem Script-based scanning is the wrong technique for engine-managed assets. A file's absence from .rpy source tells you nothing about whether the engine will try to load it at runtime.

What's actually in game/gui/

A default Ren'Py project ships with at least 30 files in gui/, covering every visual layer of the built-in UI system:

  • Menu backgrounds (main_menu.png, game_menu.png)
  • Dialogue window frames (window.png, frame.png)
  • Button states (button/idle.png, button/hover.png, button/selected_idle.png)
  • Scrollbar and slider graphics
  • Checkbox and radio button states
  • Bar fill and empty images

These are loaded unconditionally when your game starts — not when a player visits a specific label or triggers a specific scene. They are part of the engine's boot sequence.

What breaks if you delete them Missing GUI images produce Missing image errors immediately on launch — before the player ever sees your opening scene. Because these images are loaded by the engine's own initialisation code, the traceback may not even point to anything recognisable in your project files.

The same problem applies to other engine-managed paths

gui/ is the most visible example, but Ren'Py maintains several other paths that are never referenced by user-written scripts:

  • renpy/ — Ren'Py core library and internal assets
  • common/ — shared Ren'Py library code
  • launcher/ — launcher-specific assets
  • fonts/ — font files that may be loaded indirectly via config.font_* or style definitions

Any tool that treats "not referenced in a .rpy file" as equivalent to "safe to delete" will produce false positives across all of these paths.

How BranchPy handles this

BranchPy classifies every file before presenting it to you. Files in engine-managed paths receive a PROTECTED classification and are excluded from any actionable set — regardless of whether they appear in scripts.

The protection is enforced at two layers:

  • No checkbox is rendered for protected files in the Unreferenced tab. There is no UI element to select them.
  • The delete handler independently validates the file set before it is sent anywhere, stripping any protected path even if it somehow appeared in the set.

The intent is that a single bug anywhere in the rendering layer cannot cause an engine-managed file to be deleted.

What BranchPy shows instead Protected files appear in the media browser with a 🛡️ icon and a reason string — for example, "Ren'Py engine-managed: GUI system" — so you understand why they're classified that way, not just that they are.

What this means for your project

If you're evaluating any asset scanner for Ren'Py work, the key question to ask is:

"Does this tool know which paths are loaded by the engine, not just which paths are referenced by my scripts?"

If the answer is no, every "unused file" result it produces is a potential false positive in the parts of your project that are most critical to your game launching at all.

Summary

  • game/gui/ files are loaded by Ren'Py's GUI system at startup, not by your scripts.
  • Script-based scanners will always flag them as unreferenced — that's a scanner limitation, not a project problem.
  • Deleting them breaks the game immediately, before any player-authored code runs.
  • The correct approach is to classify and protect these paths before presenting results, not after.