Using and Creating Resources in Godot 4

Any game out there needs assets like textures, sounds, and music to provide a fun experience to its players. Godot treats these files as resources you can use throughout your project. Besides Godot’s built-in resources, you can also create your own to build powerful, modular systems. Custom resources make it easier to manage your project. […] By Eric Van de Kerckhove.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 5 of 5 of this article. Click here to view the first page.

Creating a Save Manager

To get started, open the shop scene again and toggle the visibility of the SaveButtons node, which is a child of CanvasLayer. To do this, click the closed eye icon at the right of its name in the Scene tree.

Eye button

This will make two buttons visible in the bottom-left of the scene: a Save Game button and a Load Game button.

Save and load buttons

At the moment, these buttons won’t do anything, but you’ll be hooking them up later.
Now create a new node as a child of the Shop node. Name it SaveManager and attach a new script to it. Name this script save_manager.gd and move it inside the scripts folder.

Save Manager node

Next, add the following code to the save_manager.gd script, below the extends line:

class_name SaveManager

# 1
@onready var shop = $".." as Shop
@onready var player: Node = $"../Player"

# 2
var shop_inventory_path : String = "user://shop_inventory.res"
var player_inventory_path : String = "user://player_inventory.res"

These are variables to have a reference to the shop and player’s inventories and paths to save the inventories to:

  1. shop and player are references to the shop and player nodes. This is needed to access their inventories.
  2. These paths point to where the inventories will be saved to and loaded from. These paths are relative to the user:// path, which point to a different path on the user’s computer depending on the operating system:
    • Windows: %APPDATA%\Godot\app_userdata\[project_name]
    • macOS: ~/Library/Application Support/Godot/app_userdata/[project_name]
    • Linux: ~/.local/share/godot/app_userdata/[project_name]

Now it’s just a matter of saving and loading the inventories. To create the saving logic, add the following function:

func save_game():
    ResourceSaver.save(shop.shop_inventory, shop_inventory_path) # 1
    ResourceSaver.save(player.player_inventory, player_inventory_path) # 2
    print("Game saved!") # 3

This function saves the shop and player inventories to the paths specified above:

  1. Use the ResourceSaver class to save the shop’s inventory to the path defined above
  2. Do the same as with the player’s inventory
  3. Print a message to the console

As you can see, it’s quite simple to save a single resource. All you need is one line of code and you’re done!
Loading the inventories is a bit more involved, but still straightforward. To do so, add the following function:

func load_game():
    if ResourceLoader.exists(shop_inventory_path): # 1
        shop.shop_inventory = ResourceLoader.load(shop_inventory_path, "", ResourceLoader.CACHE_MODE_IGNORE) # 2
        # 3
        shop.update_shop_items_display()
        print("loaded shop inventory")

    # 4
    if ResourceLoader.exists(player_inventory_path):
        player.player_inventory = ResourceLoader.load(player_inventory_path, "", ResourceLoader.CACHE_MODE_IGNORE)
        shop.update_player_items_display()
        print("loaded player inventory")

When loading a resource, you want to make sure that it exists before you try to load it using the ResourceLoader.exists() function. Otherwise, you’ll get a nasty error.
Here’s a summary of this code:

  1. Use the ResourceLoader.exists() function to check if the shop’s inventory path exists
  2. Use the ResourceLoader.load() function to load an inventory from disk and overwrite the shop’s existing inventory. The CACHE_MODE_IGNORE parameter tells Godot to ignore the cache when loading the resource, more on that below.
  3. Call the update_shop_items_display() function to update the shop’s inventory display. Also print a message to the console.
  4. Do the same as with the shop’s inventory, but update the player’s inventory and its display instead.

There’s one thing you might be wondering if you ever used the load() function before to load a resource: why not use that instead of the ResourceLoader.load() function?

The reason is that the load() function is a simplified version of ResourceLoader.load() that uses the default parameters, including its cache mode. Cache mode is an Enum with three possible values:

  • CACHE_MODE_IGNORE: The resource will not be cached. This will load the resource data from disk every time.
  • CACHE_MODE_REUSE: This is the default behavior. If a resource is already loaded in the cache, it will be reused. If not, it will be loaded from disk.
  • CACHE_MODE_REPLACE: The resource will be reloaded and cached, even if it was already cached.

Godot keeps tracks of what paths you load resources from and caches the resources in memory. For most resources, the default cache mode is optimal, as that loads the resource only once from disk. You don’t want to load the same bullet sprite hundreds of times for example.

For a dynamic resource like a saved game that you can save and reload anytime, CACHE_MODE_IGNORE is the best option. It ensures that the save game is loaded fresh from the disk each time. The other modes will prefer to reuse the resource if it’s already cached, even CACHE_MODE_REPLACE, resulting in no new data being loaded.

Connecting the Save and Load Buttons

That was quite the detour, but you’re almost done! The final step is to hook up the save and load buttons to their matching functions via the editor.
Save the save_manager.gd script and select the SaveButton node in the node tree. It’s a child of the SaveButtons node.

SaveButton node

Now open the Node tab at the right side of the editor, next to the Inspector tab and double-click its pressed signal.

Pressed signal

This will open the signal connection window. Select the SaveManager node in here and click the Pick button to open the list of functions.

Save Manager and pick button

Double-click the save_game() function to link it to the button’s pressed signal.

Save game function

Finally, click the Connect button to confirm the connection. Do the same for the LoadButton and the load_game() function.

Great job, now all that’s left to do is playing the project to test the save and load buttons. You can do this by buying a monster and clicking the Save Game button. Check if “Game saved!” appears in the output window. Now buy some more monsters and click the Load Game button. If all went well, the player will be left with a single monster in their inventory.

Saving and loading

That’s it, you’re now a master of resources in Godot!

Where to Go From Here?

You can download the final project at top or bottom of this tutorial by clicking the Download materials link.

Thanks for reading this tutorial to the end, I hope you enjoyed it. Now you know how resources work in Godot and how to make your own, I recommend to experiment with them in your own projects. Custom resources in particular make for a great addition to your game development tool belt.

If you have any questions or feedback, please join the discussion below.
A lot more tutorials about Godot and its features are coming soon, so stay tuned!

Contributors

Over 300 content creators. Join our team.