Why inventory icons drift out of style
Most inventory art fails slowly. You make a sword on Monday, a potion two weeks later in a different tool, then a shield from a free pack. Each piece looks fine alone, but together the shapes, line weight, and colors clash. Players notice this fast in a grid or shop UI where icons sit side by side.
This is a good place for asking AI to unblock you instead of asking it to design the whole game. You stay in charge of style, while generation handles the repetitive variations. The goal of this tutorial is a small set of six item icons that share one style and actually load in Godot.
Build one reusable art template
Start with a template, not a single prompt. A template records the choices you want to repeat for every icon, so number seven still matches number one. Write it down in a text file you can paste again later.
| Slot | Choice for this tutorial | Why it matters |
|---|---|---|
| Size | 128 by 128, centered icon | Keeps grid alignment simple |
| Background | Solid transparent background | Works over any UI panel |
| Style | Flat fantasy, soft shading, thick outline | Reads well at 64 pixels |
| Palette | Muted blues and browns with one accent | Avoids neon clashes |
| View | Straight on, single item, no scene | Keeps items comparable |
Keep the list short:
- One style sentence you reuse word for word
- One background rule, transparent in this case
- One size rule and one palette note
- A naming rule like
item_id.pngin lower case
If you use Godot MCP Studio, save that text file as a reusable template next to your project notes. When you return for new items next month, you load the same template instead of trying to remember the wording. That one habit does more for consistency than any single anchor icon.
Generate a matching icon set step by step
Work in a fixed folder from the start. Create res://assets/icons in Godot first, so every generation has a known destination and name.
- Paste your template into Image Studio and generate the first anchor icon. Use
health_potionas the anchor, since round shapes expose style drift fast. - Lock what worked. Keep the style sentence identical and only change the subject for the next five items:
iron_sword,wooden_shield,mana_crystal,bronze_key,leather_boots. - Generate in small batches of two or three. Compare them zoomed out at shop size, not full screen. Reject anything with a background scene or extra props.
- Fix outliers with a second pass. Ask for the same icon with simpler shape and stronger outline, still using the same template text.
- Save final PNG files with exact names into
res://assets/icons. You should end with six files that look like one set.
Because tool access changes AI development, you can let the assistant write files straight into that folder when that workflow is available in your setup. You still review each icon visually, but you skip manual downloading and renaming.
Tip: Keep one rejected icon. It makes a useful negative example when you need to explain what to avoid in the next batch.
Import and wire icons into a working inventory
Godot will import the PNG files automatically once they are in the project folder. Select the six icons, and in the Import tab keep the texture filter on for crisp UI and confirm the scale matches your UI design.
Now build a tiny inventory to prove the set works:
- Create a
Controlscene with aMarginContainerthat holds aGridContainer. Set the grid columns to 3. - Attach a script to the root
Controlthat loads each icon byitem_idand builds a row with aTextureRectand aLabel. - Run the scene and check alignment at 100 percent scale. Icons should share visual weight with no single icon looking blurry or oversized.
- Replace any weak icon by regenerating from the same template, keeping the file name unchanged so the scene picks it up without edits.
Use this complete script on the root Control:
extends Control
@onready var grid: GridContainer = $MarginContainer/GridContainer
var items: Array = [
{"id": "health_potion", "name": "Health Potion"},
{"id": "iron_sword", "name": "Iron Sword"},
{"id": "wooden_shield", "name": "Wooden Shield"},
{"id": "mana_crystal", "name": "Mana Crystal"},
{"id": "bronze_key", "name": "Bronze Key"},
{"id": "leather_boots", "name": "Leather Boots"}
]
func _ready() -> void:
for child in grid.get_children():
child.queue_free()
for item in items:
var item_id: String = String(item["id"])
var item_name: String = String(item["name"])
var icon_path: String = "res://assets/icons/%s.png" % item_id
var texture: Texture2D = load(icon_path) as Texture2D
var box := VBoxContainer.new()
box.custom_minimum_size = Vector2(96, 112)
var rect := TextureRect.new()
rect.custom_minimum_size = Vector2(64, 64)
rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
if texture != null:
rect.texture = texture
var label := Label.new()
label.text = item_name
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
box.add_child(rect)
box.add_child(label)
grid.add_child(box)Press Play. You should see six labeled icons in two rows of three, all sharing outline weight and palette. From here you can extend the same template for rarity borders, drag and drop, or tooltips, knowing new art will match the set you just proved in game.