The Godot Barn
Sign in
Sign in
Home
News & updates
Explore
Tutorials
Articles
Snippets
Shaders
Submit content
Sign in to submit content
Give or get help
Questions
Conversations
Coming soon!
How to Make UI in Godot
2
Description
"You can read the original and more detailed blog from here: [My Original Blog](https:\/\/eakyrtk.com\/how-to-make-ui-in-godot-4\/) \r\n\r\n# The Beginning\r\n\r\nAs a beginner, making UI can be very confusing. Godot handles the UI processes well for me, but for beginners it's a bit confusing, not gonna lie. I know this from myself and my friends who have tried to do UI in Godot. So in this blog I will guide you on how to handle the UI in Godot 4. In this blog post you will learn how to do the UI in the header image!\r\n\r\nAnd! I will give you a homework to experiment with and learn different things. In this demo, I made it so that it'll be easier for you to learn the topics when you do your homework.\r\n\r\n## Framework\r\nFirst thing first we need a framework.\r\n* Title at the top\r\n* Shop is scrollable\r\n* Pre-made item slots will be added to a container that we can scroll.\r\n* This slot will have a texture rect, a name label, lore text, price and a buy button.\r\n\r\n![](\/files\/17383d14-a667-427e-8e06-39b3d221f4cb)\r\nThis will be our design for the shop.\r\n\r\nYou can search for Godot Nodes tutorial for more in-depth for more explanation. But this will be our general framework for this demo:\r\n\r\n![](\/files\/7e00aa86-8f97-4b67-8cf1-4e51925d5d64)\r\n\r\nHaving a debug panel is always helpful but making the design more accurate to the original size we will use 'Stretch Ratio'. This values will give 3\/4 space for actual Shop UI and 1\/4 space for the debug panel.\r\nAlso one thing, we don't want to save things as a different scene for now. Because by keeping them in scene for now, we can duplicate UI elements, change values, compare and keep the better one. Also its better to test if things work okay. When everything is finished we can save stuff as a scene to instance. \r\n\r\n![](\/files\/0ae5f98b-e1e4-472f-93cb-838dc267b008)\r\nWe used scroll container for scrolling ability and added VBoxContainer as a child to it. This nodes organizes the nodes in vertical order so adding it as a child to the Scroll Container grants us vertical scrolling UI.\r\n\r\n## Database\r\nCreating every UI element as a different scene would be so much work. Instead we are going to create Custom Resources and use it as a database. \r\nIt will be a script and it looks like this:\r\n```\r\n@icon(\"res:\/\/item\/item.svg\")\r\nclass_name Item extends Resource\r\n\r\n@export var item_texture : CompressedTexture2D\r\n@export var item_price : float\r\n@export var item_name : String\r\n@export var item_lore : String\r\n```\r\nwith this we can create and save infinite amount of items in any folder.\r\n\r\nIn any folder we want, we will create a resource and give the values we want to:\r\n\r\n![](\/files\/65194381-669b-4b97-94e8-64d0b33666d2)\r\n\r\n## Way to Approach Resources\r\nWe can create an autoload to access these resources. Autoload is outside of the scene we play and doesn't go away when we change the scenes. Also it can be accessible from anywhere.\r\n\r\nSo we create an autoload script like this and add it in project settings:\r\n```\r\nextends Node\r\n\r\nvar player_money : float = 100.0 :\r\n \/\/debt preventor\r\n\tset(value):\r\n\t\tif value < 0: player_money = 0\r\n\t\telse: player_money = value\r\n\t\t\r\nvar player_inventory : Array[String]\r\n\r\nconst items = {\r\n\t\"face\": preload(\"res:\/\/item\/item_resources\/face.tres\"),\r\n\t\"stick\": preload(\"res:\/\/item\/item_resources\/stick.tres\"),\r\n\t\"sun\": preload(\"res:\/\/item\/item_resources\/sun.tres\"),\r\n\t\"sword\": preload(\"res:\/\/item\/item_resources\/sword.tres\"),\r\n\t\"tree\": preload(\"res:\/\/item\/item_resources\/tree.tres\")\r\n}\r\n\r\nfunc add_item_to_player(item_name: String)->void:\r\n\tplayer_inventory.append(item_name)\r\n```\r\n\r\nWith this script everything is String oriented this will make our jobs easier in a minute.\r\n\r\n## Item UI\r\nWe have our database, our interface (autoload) to access it, now the next step is making an UI element to insert these values.\r\n\r\n![](\/files\/8636df75-0408-407a-9b44-9d2572f31cfa)\r\nOur Item UI is ready, we tested with random values and we are ready to save it as a scene and insert values from the code.\r\n\r\nThis UI can access our autoload and insert values from our resources by just the name string of it and the script is like this:\r\n\r\n```\r\n@icon(\"res:\/\/GUI\/shop_slot.svg\")\r\nclass_name ItemUISlot extends Control\r\n\r\n@onready var item_texture_rect: TextureRect = %ItemTextureRect\r\n@onready var item_name_label: Label = %ItemName\r\n@onready var lore_rich_text: RichTextLabel = %Lore\r\n@onready var price_label: Label = %PriceLabel\r\n@onready var buy_button: TextureButton = %BuyButton\r\n\r\n\r\nfunc insert_values(item_name: String)->void:\r\n\titem_texture_rect.texture = Global.items[item_name].item_texture\r\n\titem_name_label.text = Global.items[item_name].item_name\r\n\tlore_rich_text.add_text(Global.items[item_name].item_lore)\r\n\tprice_label.text = str(Global.items[item_name].item_price)\r\n```\r\nBy calling this function and for example saying `insert_values(\"tree\")` we can get the texture, price, name etc.\r\n\r\nBut we need to add these Item UI elements in the scrollable node. For this we need a Manager script that handles this stuff.\r\n\r\n## GUI Manager\r\nWith GUI manager and its simple script we can instance that Item UI node, add it to the scrollable UI:\r\n\r\n```\r\n\r\nextends Control\r\n\r\nconst SLOT = preload(\"res:\/\/GUI\/slot.tscn\")\r\n@onready var _item_content_box: VBoxContainer = %ItemContentVBox\r\n\r\nfunc add_item_slot(item_name: String) -> void:\r\n\tif not Global.items.keys().has(item_name): return\r\n\t\r\n\t_item_content_box.add_child(new_item_slot)\r\n\t# item_name is like a variable, we store item_name in the node\r\n \t# as item_name\r\n\tnew_item_slot.set_meta(\"item_name\", item_name)\r\n\tnew_item_slot.buy_button.pressed.connect(_item_bought.bind(new_item_slot))\r\n\r\n\t\r\n\tnew_item_slot.insert_values(item_name)\r\n```\r\n\r\nBy calling this function in the gui manager we can add any item to the shop. But there are some things to explain.\r\nWhat is meta? Metadata is like storing a variable in a node without creating a script for that node. In this instance we want to store the item's name in the Item UI element, so when we click buy we can get that value back and call the `add_item` in autoload to add that to the player. There are other ways to this but what I want to teach is, when connecting signals you can .bind them and can pass the node itself. As you can see the Buy Button's pressed signal connects to a function in the GUI Manager, and it looks like this:\r\n\r\n```\r\n\r\nfunc _item_bought(item_slot: ItemUISlot)->void:\r\n\titem_slot.buy_button.disabled = true\r\n\tif not item_slot.has_meta(\"item_name\"):\r\n\t\tprint_rich(\"[color=red]BRO[\/color]\") \r\n\t\treturn\r\n\t\r\n\taudio_stream_player.play()\r\n \/\/we take item_name from that node back and adding to the player\r\n\tGlobal.add_item_to_player(item_slot.get_meta(\"item_name\"))\r\n\titem_slot.get_lost_lol()\r\n```\r\nWhen we click buy, because when connecting the signal we also passed the node itself as a parameter, we can get the metadata that we assigned to the node back. Also do whatever we want with that node. For this demo we just get the item name String and add to the player and call the Item UI's getting deleted function so it goes away.\r\n\r\n# The End\r\nThis is more shortened version of my actual blog post. You can go to the blog with this [link](https:\/\/eakyrtk.com\/how-to-make-ui-in-godot-4\/)\r\nAlso there is a presentation in the source code, its a .excalidraw file that you can import to the excalidraw.com website. It has more detailed explanation. Also the source code has comment explanations and stuff so you can toy around there too.\r\n\r\nThe homeworks I gave also can teach you some more stuff and if there are still missing pieces you can search for amazing tutorials other amazing people make ^_^"
Comments
Log in to post a comment
Licensed under the CC-BY license
See the full license details
Submitted by
EakyRtkLeBoi
Open on Github
Code for this tutorial is also available on Github
Table of contents
Compatibility
Works in Godot
4.x
Tags
UI
autoload
Signals
custom resource
Share this tutorial
Share on Bluesky
Share on X / Twitter
or share this direct link:
https://thegodotbarn.com/contributions/tutorial/135/how-to-make-ui-in-godot
Please wait ...
Okay
Okay
No
Yes
Okay