Why Ren'Py GUI files appear unused — but deleting them breaks your game
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:
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.
.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.
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 assetscommon/— shared Ren'Py library codelauncher/— launcher-specific assetsfonts/— font files that may be loaded indirectly viaconfig.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 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.