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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Using and Creating Resources in Godot 4
40 mins
- Getting Started
- Shop
- Player Item Display
- Shop Item Display
- What are Resources?
- Importing and Using Resources
- Applying a Sprite Texture
- Import Parameters
- External vs Built-in Resources
- Creating Custom Resources
- Your First Custom Resource
- An Inventory of Items
- Using Custom Resources
- The Shop Inventory
- Creating a Shop Display
- Showing the Shop Items
- Making Smart Resources
- Inventory Logic
- Player Script
- Displaying Player Items
- Saving and Loading Custom Resources
- Creating a Save Manager
- Connecting the Save and Load Buttons
- Where to Go From Here?
Creating a Shop Display
Printing some text to the output window is great and all, but displaying the items with their sprites and other properties is more fun!
To get that done, you’ll need to add some logic to the shop item display so it can fill in its labels based on an item. Once that’s done, the shop script can instantiate the shop item displays based on its inventory.
To add some logic, you’ll need a new script, so open the shop_item_display scene and select the ShopItemDisplay node at its root. Add a new script to it named shop_item_display.gd and make sure to place it in the scripts folder.
Here’s what this script should do:
- Get references to the sprite, labels and the button
- Store a reference to an item
- Update the UI elements based on the item’s properties
- Emit a signal when the buy button was pressed
To start off, add the following code below the extends line:
class_name ShopItemDisplay # 1
signal buy_pressed(item_display : ShopItemDisplay, item : Item) # 2
Here’s a summary of this code:
- As always, a class name helps with static typing as you’ll see in the next line.
- This signal will be emitted when the buy button is pressed. It has two parameters: the item display that emits the signal and the item that’s being sold by the display. This signal will be used by the shop script later on.
Next up are the references to the Control nodes. To add these, select all children of the BackgroundTexture node and drag them to the code editor while holding Control/Cmd. This will create all necessary @onready
variables.
Here’s the code it added:
@onready var sprite_texture: TextureRect = %SpriteTexture
@onready var name_label: Label = %NameLabel
@onready var hp_label: Label = %HpLabel
@onready var attack_label: Label = %AttackLabel
@onready var defense_label: Label = %DefenseLabel
@onready var buy_button: Button = %BuyButton
Now add these lines of code below the @onready
variables:
var linked_item : Item # 1
func link_to_item(item : Item): # 2
linked_item = item # 3
_update_info() # 4
You’ll get an error because the _update_info
function isn’t defined yet, but ignore that for now.
The link_to_item
function will be called by the shop script while adding new shop displays. It will store a reference to an item in the linked_item
variable and call the _update_info
function to update the display.
Here’s what this code does line-by-line:
- The
linked_item
variable stores a reference to an item - A function called
link_to_item
that takes an item as a parameter - Store the item reference in the
linked_item
variable - Call the
_update_info
function to update the display
Now add the following code below the link_to_item
function:
func _update_info():
# 1
name_label.text = linked_item.item_name
sprite_texture.texture = linked_item.sprite
hp_label.text = str(linked_item.hp)
attack_label.text = str(linked_item.attack)
defense_label.text = str(linked_item.defense)
buy_button.text = "Buy\n" + str(linked_item.price) + "G" # 2
buy_button.pressed.connect(_on_buy_pressed) # 3
func _on_buy_pressed():
buy_pressed.emit(self, linked_item) # 4
The _update_info
function will update the display based on the item’s properties. It will also link the buy button’s pressed
signal to the _on_buy_pressed
function. The _on_buy_pressed
function in turn will emit the buy_pressed
signal.
Here’s what’s going on in more detail:
- Update the all labels based on the properties of the item. The
str
function is used on integers to convert them to strings. - The text of the buy button is updated to include the price of the item
- Connect the buy button’s
pressed
signal to the_on_buy_pressed
function - Emit the
buy_pressed
signal and pass the shop item display and the item
That finishes up this script! Save it and open the shop.gd script again.
Showing the Shop Items
The shop script should create a shop item display for each item in its inventory.
For that to work, it needs a reference to a Control node where it can put the displays and a reference to the shop display scene.
First, add these two variables below the shop_inventory
variable declaration:
@onready var shop_item_display_h_box: HBoxContainer = %ShopItemDisplayHBox # 1
@export var shop_item_display_scene : PackedScene # 2
Here’s what they’re for:
-
shop_item_display_h_box
is a reference to the HBoxContainer node, this is where you will put the shop item displays - The
shop_item_display_scene
export variable will reference the shop_item_display scene
Next, add this function below the _ready
function:
func update_shop_items_display():
for child in shop_item_display_h_box.get_children(): # 1
child.queue_free()
for item in shop_inventory.items: # 2
var new_item_display = shop_item_display_scene.instantiate() as ShopItemDisplay # 3
shop_item_display_h_box.add_child(new_item_display) # 4
new_item_display.link_to_item(item) # 5
new_item_display.buy_pressed.connect(_on_item_display_buy_pressed) # 6
This function will first remove all existing shop item displays. It will then instantiate a shop item display for each item in the shop’s inventory. Finally, it connect the buy_pressed
signal to the _on_item_display_buy_pressed
function, which you’ll add next.
Here’s how it works:
- Loop through the existing children (the item displays) of the HBoxContainer and remove them
- Loop through the items in the shop’s inventory
- Instantiate a new shop item display
- Add the display to the HBoxContainer
- Pass the item to the shop item display to link it
- Connect the shop item display’s
buy_pressed
signal to the_on_item_display_buy_pressed
function
Now for _on_item_display_buy_pressed
, add this below the update_shop_items_display
function:
func _on_item_display_buy_pressed(item_display : ShopItemDisplay, item : Item): # 1
print("Sold " + item.item_name) # 2
item_display.queue_free() # 3
This will print the sold item name to the output window and remove its item display:
- This function is called when the buy button is pressed, it has the same parameters as the
buy_pressed
signal - Print the sold item name
- Remove the item display
To finish up the script for now, the update_shop_items_display
function should be called when the shop loads. Remove all code from _ready
function and add this line in its place:
update_shop_items_display()
To get the displays to work, save the script and drag the shop_item_display scene from the scenes/shop_ui folder in the FileSystem dock onto the Shop Item Display Scene property of the Shop node.
Now run the project and try buying some items! The displays should reflect the items in the inventory. Whenever you click a buy button, the display should disappear and the item’s name should be printed to the output window.
As a cherry on top, open the shop script again and add a reference to the CashSound node right above the _ready
function:
@onready var cash_sound = $CashSound
You’ll use this to play a nice cash register sound when you buy an item. Add this line at the end of the _on_item_display_buy_pressed
function to do so:
cash_sound.play()
Save the script and run the project once more. You should hear a satisfying sound play now whenever you buy an item.
Almost feels like a shop you’d find in a monster-collecting game, right? :]
To take your custom resource skills to the next level, you’re going to add some logic to the Inventory resource.