Belajar Godot - UI & HUD Development
Episode 8 of 23

Belajar Godot - UI & HUD Development

Episode ini fokus pada antarmuka: hirarki Control nodes, container dan layout system, beragam widget seperti button, label, slider, dan menu, teknik responsive UI dengan anchoring, serta menghubungkan sinyal UI ke logika game yang sebenarnya.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Dua episode terakhir kalian membangun dunia — pertama 2D, lalu 3D. Tapi pemain tidak hanya butuh dunia; mereka butuh cara berkomunikasi dengannya. Di episode 6 kita sempat menyinggung CanvasLayer sebagai overlay. Episode 8 ini adalah pembahasan penuh tentang antarmuka: UI & HUD. Di sini kalian belajar menyusun layout yang rapi, membuat menu yang fungsional, dan menyambungkan semua widget ke logika game.

Roadmap episode ini: kita mulai dari Control node sebagai dasar segala UI, mempelajari container dan layout system, mengenal widget-widget utama seperti Button, Label, Slider, dan PanelContainer, lalu membuat UI responsive dengan anchoring, dan menutupnya dengan menghubungkan sinyal UI ke interaksi logika game.

Control Node: Dasar Segala UI

Semua elemen antarmuka di Godot menurun dari node Control. Control punya sistem koordinat sendiri yang berbeda dari dunia: position dihitung dari pojok kiri-atas, dan ukuran diatur lewat properti size. Ini mengapa UI tidak ikut berubah saat kamera bergeser — ia hidup di ruang layar, bukan di ruang dunia.

Ada tiga properti kunci pada setiap Control: position (pojok kiri-atas), size (lebar dan tinggi), dan anchor. Untuk menempatkan elemen dengan presisi, letakkan semua UI di dalam CanvasLayer atau langsung sebagai child scene Control root. Godot juga menyediakan panel Layout di toolbar editor yang mengatur anchor dan offset secara visual.

Pythoncontrol_props.gd
extends Control
 
func _ready() -> void:
    position = Vector2(20, 20)
    size = Vector2(200, 50)
    print("rect global: %s" % get_global_rect())

Jangan tergoda untuk menaruh Label atau Button langsung di scene world — tanpa Control parent yang menempel layar, posisinya akan bergeser-geser tidak terkendali. Selalu bungkus UI di CanvasLayer atau Control root.

Containers & Layout System

Menaruh widget satu per satu dengan koordinat manual itu menyiksa — dan hancur begitu resolusi layar berubah. Solusinya adalah container: node yang mengatur posisi dan ukuran child-nya secara otomatis. Cukup buat VBoxContainer atau HBoxContainer, masukkan beberapa Button, dan Godot menyusunnya rapi berurutan tanpa kalian menyentuh satu angka pun.

Container populer yang wajib kalian tahu:

  • VBoxContainer — menyusun child vertikal dari atas ke bawah.
  • HBoxContainer — menyusun child horizontal dari kiri ke kanan.
  • GridContainer — menyusun child dalam grid sesuai kolom yang ditentukan.
  • MarginContainer — menambah jarak di sekeliling isinya.
  • CenterContainer — memusatkan child di tengah area.

Container menghormati properti size_flags_horizontal dan size_flags_vertical pada tiap child. Set EXPAND agar child mengisi ruang ekstra, atau SHRINK_CENTER agar tetap di tengah. Contoh menu sederhana:

Pythonmenu_layout.gd
extends VBoxContainer
 
func _ready() -> void:
    add_button("Start Game")
    add_button("Settings")
    add_button("Quit")
 
func add_button(text: String) -> void:
    var button := Button.new()
    button.text = text
    add_child(button)

Hasilnya tiga tombol tersusun rapi vertikal dan otomatis menyesuaikan diri. Container adalah kunci produktivitas UI di Godot — gunakan berlapis: MarginContainer > VBoxContainer > barisan HBoxContainer untuk layout yang kompleks.

Button, Label, Slider, & Menus

Godot menyediakan widget siap pakai untuk hampir semua kebutuhan UI:

  • Label — teks statis atau dinamis untuk skor dan pesan.
  • Button — aksi yang bisa diklik; punya varian CheckButton, ToggleButton, dan OptionButton.
  • LineEdit — input teks satu baris untuk nama pemain.
  • HSlider dan VSlider — kontrol nilai kontinu, pas untuk volume dan kecepatan.
  • ProgressBar — menampilkan nilai dalam bentuk batang.
  • PanelContainer / Panel — wadah visual dengan background untuk menampung elemen lain.
  • PopupMenu — dropdown menu kontekstual.

Menata sebuah halaman settings biasanya menyatukan beberapa widget tersebut dalam container. Misalnya baris volume terdiri dari Label ("Music"), HSlider, dan Label persentase — semua di dalam satu HBoxContainer. Untuk menu utama, bungkus semua tombol dalam CenterContainer lalu beri PanelContainer sebagai latar agar terlihat seperti menu sungguhan.

Info

Godot memiliki tema global untuk UI. Atur Theme di project settings agar semua Button, Label, dan Panel memakai gaya konsisten tanpa styling satu per satu. Untuk polish cepat, atur StyleBoxFlat pada panel: beri warna background, corner radius, dan border.

Responsive UI & Anchoring

Layar game tidak selalu sama: dari ponsel portrait sampai monitor ultrawide. Agar UI tetap benar di semua kondisi, kalian pakai anchoring. Anchor menentukan bagian mana dari area parent yang menjadi acuan posisi. Empat pojok anchor: kiri-atas (0,0), kanan-bawah (1,1).

Beberapa pola anchor yang umum:

  • Full rect — anchor semua pojok di (0,0) sampai (1,1); elemen meregang mengikuti ukuran layar. Dipakai untuk background dan container utama.
  • Top center — anchor horizontal tengah, misal untuk label judul.
  • Bottom right — untuk minimap atau tombol pause.
  • Center — untuk panel popup di tengah layar.

Anchor bekerja berpasangan dengan offset (jarak dari anchor) dan grow_direction (arah berkembang saat ukuran parent berubah). Untuk panel popup yang selalu di tengah berapa pun resolusinya, cukup atur anchor center dan biarkan offset-nya otomatis. Contoh menempatkan tombol di pojok kanan-bawah:

Pythonanchor_setup.gd
extends Button
 
func _ready() -> void:
    anchors_preset = Control.PRESET_BOTTOM_RIGHT
    offset_left = -200.0
    offset_top = -50.0
    offset_right = -20.0
    offset_bottom = -20.0

Perhatikan: dengan anchor bottom-right, offset bernilai negatif berarti "mundur dari tepi". Pola ini membuat tombol selalu menempel pojok kanan-bawah di layar berapa pun ukurannya.

Menghubungkan Sinyal UI

UI tanpa logika hanyalah gambar. Jembatan antara keduanya adalah sinyal. Semua widget mengeluarkan sinyal: Button memancarkan pressed, HSlider memancarkan value_changed, LineEdit memancarkan text_submitted. Kalian bisa menyambungkannya di editor lewat panel Node, atau secara programatik dengan connect().

Cara paling idiomatis di Godot 4 adalah lewat anotasi @onready dan referensi node, lalu connect() di _ready():

Pythonui_signals.gd
extends Control
 
@onready var start_button: Button = %StartButton
@onready var volume_slider: HSlider = %VolumeSlider
 
func _ready() -> void:
    start_button.pressed.connect(_on_start_pressed)
    volume_slider.value_changed.connect(_on_volume_changed)
 
func _on_start_pressed() -> void:
    get_tree().change_scene_to_file("res://scenes/game.tscn")
 
func _on_volume_changed(value: float) -> void:
    AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Music"), value)

Perhatikan anotasi %StartButton — ini adalah unique name yang dipakai Godot 4 agar referensi node tidak putus walau hierarki berubah. Sinyal UI bekerja persis seperti sinyal yang kalian buat sendiri di episode 5: emit dari widget, terima di script. Inilah cara membuat UI berbicara dengan logika game.

Interaksi Logika Game

Sinyal yang terhubung adalah setengah jalan; separuh lainnya adalah logika yang menjalankan konsekuensinya. Untuk HUD, pola yang umum adalah menyimpan referensi ke node game dan memperbarui Label setiap kali nilai berubah. Contoh: counter skor yang bertambah saat koin diambil.

Pythonhud.gd
extends Control
 
@onready var score_label: Label = %ScoreLabel
 
var score := 0
 
func add_score(points: int) -> void:
    score += points
    score_label.text = "Skor: %d" % score

Saat Area2D koin terdeteksi (pola dari episode 6), panggil get_node("../HUD").add_score(10) atau lebih baik lagi lewat sinyal kustom coin_collected yang dikirim HUD. Dengan cara ini HUD tidak perlu tahu detail deteksi koin — ia hanya mendengarkan dan memperbarui tampilan. Pemisahan inilah esensi arsitektur UI yang sehat.

Satu pola lagi yang berguna: paused menubar. Tombol pause di pojok layar memanggil get_tree().paused = true lalu menampilkan CanvasLayer berisi menu. Logikanya tetap UI sederhana — satu tombol mengubah status tree, satu panel muncul. Kita akan membedah pause menu secara penuh di episode 9 bersama state management.

Penutup

Episode 8 membekali kalian dengan seluruh toolkit antarmuka: Control node sebagai dasar, container untuk layout otomatis, widget-widget standar seperti Button, Label, dan Slider, anchoring untuk UI yang responsive, serta sambungan sinyal yang menghubungkan UI ke logika game.

Inti yang harus dibawa pulang:

  • Seluruh UI menurun dari Control dan hidup di ruang layar, terpisah dari dunia game.
  • Gunakan container berlapis untuk layout; hindari koordinat manual yang rapuh terhadap perubahan resolusi.
  • Anchor menentukan pola responsif: full rect untuk background, center untuk popup, bottom-right untuk tombol pause.
  • Hubungkan logika lewat sinyal widget (pressed, value_changed) dan pola %UniqueName.
  • Pisahkan HUD dari logika dunia dengan sinyal kustom — HUD cukup mendengarkan dan menampilkan.

Di episode 9 kalian masuk ke urusan yang lebih serius: Game State & Data Persistence. Kita akan membangun autoload singleton untuk game state, menyimpan dan memuat data dengan JSON serta ConfigFile, merancang scene transition dan state machine, sampai membuat pause menu dan settings yang benar-benar tersimpan. Sampai jumpa di dunia state!

Belajar Godot - UI & HUD Development | Belajar Godot