Menu
CoddyTech

RefCounted vs Node

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GDScript di Coddy. Pelajaran 43 dari 65.

Setiap object menggunakan memori sampai dibebaskan. RefCounted dan Node dibebaskan dengan cara yang berbeda.

object RefCounted menghitung variabel, array, dan object yang merujuk kepadanya. Saat hitungannya turun menjadi nol, Godot membebaskannya sendiri. NOTIFICATION_PREDELETE, dari bab Special Methods, menunjukkan saat itu terjadi:

# note.gd
class_name Note
extends RefCounted

func _notification(what: int) -> void:
	if what == NOTIFICATION_PREDELETE:
		print("Note freed")

# main.gd
func write() -> void:
	var note := Note.new()
	print("Note written")

func _ready():
	write()          # Note written, lalu Note freed
	print("Back in _ready")

note adalah satu-satunya referensi, jadi note dibebaskan segera setelah write() selesai.

Node tidak dihitung. Node di scene tree dibebaskan bersama parent-nya, dan seluruh tree dibebaskan saat game berakhir. Node yang kamu keluarkan dari tree, atau tidak pernah kamu tambahkan ke dalamnya, harus kamu bebaskan sendiri:

crate.free()         # dibebaskan sekarang, beserta semua turunannya
crate.queue_free()   # dibebaskan di akhir frame saat ini

Setelah free(), node tersebut sudah tidak ada: is_instance_valid(crate) mengembalikan false, dan memanggil method pada node tersebut akan menghasilkan error. queue_free() adalah pilihan yang aman saat kode lain mungkin masih menggunakan node tersebut dalam frame ini, tetapi sampai frame itu berakhir, node tetap berada di dalam tree dan tetap dihitung oleh get_child_count().

Node yang tidak pernah dibebaskan adalah kebocoran memori: Godot melaporkan "Instance ObjectDB bocor saat program berakhir" ketika program berakhir. Object RefCounted juga mengalami kebocoran jika dua object saling merujuk, karena jumlah referensi keduanya tidak bisa mencapai nol. Simpan tautan hanya dalam satu arah, atau simpan nama alih-alih object.

Gunakan RefCounted untuk data: item, skor, catatan. Gunakan Node untuk hal-hal yang berada di pohon scene.

challenge icon

Tantangan

Mudah

Node Wave menyimpan musuhnya sebagai node anak. enemy.gd sudah lengkap: Enemy.new("Goblin", 5) membuat node musuh bernama Goblin dengan 5 HP. Tulis tiga method Wave:

  • spawn(enemy_name, hp) menambahkan musuh baru sebagai node anak. Jika ada node anak dengan nama tersebut, fungsi ini mencetak Orc is already here dan tidak membuat apa pun.
  • hit(enemy_name, damage) mengurangi hp musuh tersebut dan mencetak Orc has 8 HP. Jika HP menjadi 0 atau kurang, fungsi ini mencetak Orc defeated dan langsung menghapus musuh untuk selamanya: pemanggilan alive() berikutnya tidak boleh menghitungnya. Nama yang tidak ada akan mencetak No Orc here.
  • alive() mengembalikan jumlah musuh yang tersisa.

Setiap node harus dibebaskan: kebocoran apa pun saat program berakhir akan membuat tes gagal. Kode yang disediakan menambahkan wave ke pohon adegan, membaca jumlah perintah berikutnya (spawn Goblin 5, hit Goblin 6, count) dan mencetak jumlah musuh yang tersisa. Untuk spawn Goblin 5, spawn Orc 12, hit Goblin 6, count, hit Goblin 1, spawn Orc 3, hit Orc 4, kode ini mencetak:

Goblin defeated
Enemies: 1
No Goblin here
Orc is already here
Orc has 8 HP
Enemies left: 1

Tulis kodemu di wave.gd dan enemy.gd. main.gd berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

extends Node

func _ready():
	# Kode input/output yang disediakan: biarkan apa adanya
	var wave := Wave.new()
	add_child(wave)
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "spawn":
			wave.spawn(parts[1], int(parts[2]))
		elif parts[0] == "hit":
			wave.hit(parts[1], int(parts[2]))
		else:
			print("Enemies: ", wave.alive())
	print("Enemies left: ", wave.alive())
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler GDScript online