Can we use `DirAccess.get_files_at` with published products?

Godot Version

4.4.1

Question

I have directory that contains +100 TRES asset files. These files are used in multiple scenes. I don’t want to drag all of these into a ResourcePreloader object in each scene & have to remember to update these objects every time I add a new asset. I’m using DirAccess.get_files_at(RESOURCE_DIR) to load the TRES files into the debug version of the game and it works great. It’s so simple and clean. Is it possible to continue this approach for the exported game?

Notes:

  • When I export, I use ‘Export all resources in this project’.
  • In debug mode, items show up in an admin menu as expected.
  • In production mode (windows & mac), items are not in the menu.
  • I want players to be able to mod the TRES files so would rather not hide them.

Here’s my code for the admin menu:

class_name AdminGui extends Control

signal opened
signal closed

var isOpen: bool = false
var currentlySelected: int = 0
const RESOURCE_DIR: String = "res://Resources_Items/"

@onready var adminInventory: AdminInventory = preload("res://Resources_Other/admin_inventory.tres")
@onready var gridContainer: GridContainer = $NinePatchRect/GridContainer
@onready var guiSlots: Array[Node] = $NinePatchRect/GridContainer.get_children()

func _ready() -> void:
	# get the files in the folder
	var files: PackedStringArray = loadItems()
	# resize the admin inventory array
	adminInventory.slots.resize(files.size())
	# load the items into the admin inventory resource file
	for i in files.size():
		var item: InventoryItem = ResourceLoader.load(RESOURCE_DIR + files[i])
		adminInventory.slots[i] = InventorySlot.new()
		adminInventory.slots[i].item = item
		adminInventory.slots[i].amount = 1
	# load the items into the admin gui
	adminInventory.updated.connect(update)
	update()

func update() -> void:
	for i in range(min(adminInventory.slots.size(), guiSlots.size())):
		guiSlots[i].update(adminInventory.slots[i])

func loadItems() -> PackedStringArray:
	return DirAccess.get_files_at(RESOURCE_DIR)

# Called when the node enters the scene tree for the first time.
func open() -> void:
	visible = true
	isOpen = true
	get_tree().paused = true
	opened.emit()
	
func close() -> void:
	visible = false
	isOpen = false
	get_tree().paused = false
	closed.emit()

Here’s what the menu looks like in debug mode when the items actually show up:

Any easy fix here that doesn’t require putting each asset into a preloader object one by one? Thanks for any help!

When you add a Resource (texture, sound, model,…) to your game godot will import it in a better suited format internally (inside the .godot/imported folder) and the original files won’t be added to the pck file when exporting the game as they aren’t needed.

The same happens with text Resourceslike *.tscn (scenes) or *.tres (other Resource types). They will be converted to binary files (they are originally human readable text files) when exporting the game unless you uncheck the editor/export/convert_text_resources_to_binary in the Project Settings (It’s enabled by default).

DirAccess has no knowledge about this so it won’t follow the *.remap/*.import files in the exported game. You can use ResourceLoader.list_directory() instead which will know and get you the correct filenames.

1 Like

@mrcdk this is awesome. Thank you! Testing this out today.