If your game has items, enemies, weapons, or spells, you've probably felt the urge to write a giant match statement that hardcodes every one of them. Custom Resources are the way out. They let you define data as files you create and edit in the editor, completely separate from your code. It's one of the most powerful ideas in Godot, and it stays hidden until someone shows you.
What a Resource is
A Resource is Godot's container for pure data. No position, no scene tree, no _process. Just values. A Texture2D is a Resource. An AudioStream is a Resource. And you can make your own.
The win: instead of describing your fifty items in code, you make fifty small data files. Designers (or you, on a different day) can create and tweak them in the Inspector without touching a script.
Define a custom Resource
Make a script that extends Resource and give it a class_name so the editor knows about it:
# item_data.gdextends Resourceclass_name ItemData@export var name: String = ""@export var icon: Texture2D@export var max_stack: int = 1@export var value: int = 0@export_multiline var description: String = ""Those @export lines are the whole point. They turn each field into something you edit visually.
Create the data files
In the FileSystem panel, right-click, New Resource, and pick ItemData (your class shows up in the list). Save it as something like health_potion.tres. Select it and the Inspector shows your fields: name, icon, stack size, value, description. Fill them in.
Make one .tres file per item. A health potion, an iron sword, a magic scroll. Each is a tiny file you can see, diff in version control, and hand off without explaining any code.
Use them in code
Load a Resource like any other asset, and read its fields:
@export var item: ItemDatafunc _ready() -> void: print(item.name, " is worth ", item.value, " gold") $Icon.texture = item.iconOr @export var item: ItemData on a pickup node, then drag the right .tres onto it in the Inspector. Now your "potion pickup" and "sword pickup" are the same scene with different data attached. No per-item scripts, no giant switch statement. Adding a new item is making a new file.
A quick note on saving
Resources are great for designing data. They're a bad idea for save files, though. A .tres can carry an embedded script, so loading a save file a player edited is a genuine security hole. For save data, serialize the important bits (an item's id and quantity) to JSON instead. I covered the why and how in the save system guide.
See it in a real system
This data-driven approach is the backbone of any good inventory, and it's exactly how our free Inventory System quest is built: items are ItemData Resources, the inventory holds references to them, and the UI reads from the data. Once it clicks, you'll reach for custom Resources for enemies, dialogue lines, abilities, and loot tables too.
FAQ
What's the difference between a Resource and a Node in Godot?
A Node lives in the scene tree, has a position, and can run logic each frame. A Resource is pure data with no scene presence, cheap to load and share. Use a Node for things that exist in the world, and a Resource for the data those things are made of, like item stats.
How do I create a custom Resource in Godot 4?
Write a script that extends Resource with a class_name and some @export variables. Then in the FileSystem panel, right-click, choose New Resource, pick your class, and save it as a .tres file. Each file is one data object you edit in the Inspector.
Should I use Resources for save files?
No. A Resource file can embed a script, so loading one a player has edited is a security risk. Use Resources to author game data, but save player progress as plain JSON containing only the values you need, like ids and quantities.