Menu
CoddyTech

RefCounted a Node

Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 43 z 65.

Każdy obiekt zajmuje pamięć, dopóki nie zostanie zwolniony. Obiekty RefCounted i Node są zwalniane na różne sposoby.

Obiekt RefCounted zlicza zmienne, tablice i obiekty, które się do niego odwołują. Gdy licznik spada do zera, Godot sam go zwalnia. NOTIFICATION_PREDELETE, omówione w rozdziale Metody specjalne, pokazuje ten moment:

# 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()          # Notatka zapisana, a następnie zwolniona
	print("Back in _ready")

note było jedynym odwołaniem, więc notatka zostaje zwolniona zaraz po zakończeniu write().

Node nie jest liczony. Węzeł w drzewie sceny jest zwalniany razem ze swoim elementem nadrzędnym, a całe drzewo jest zwalniane po zakończeniu gry. Węzeł, który usuniesz z drzewa lub którego nigdy do niego nie dodasz, musisz zwolnić samodzielnie:

crate.free()         # zwolniony teraz, wraz ze wszystkimi swoimi elementami potomnymi
crate.queue_free()   # zwolniony na końcu bieżącej klatki

Po wywołaniu free() węzeł znika: is_instance_valid(crate) zwraca false, a wywołanie na nim metody powoduje błąd. queue_free() to bezpieczny wybór, gdy inny kod może jeszcze używać węzła w tej klatce, ale do końca tej klatki węzeł pozostaje w drzewie i nadal jest uwzględniany przez get_child_count().

Węzeł, który nigdy nie jest zwalniany, powoduje wyciek pamięci: Godot zgłasza komunikat „ObjectDB instances were leaked at exit” po zakończeniu programu. Obiekty RefCounted również powodują wycieki, gdy dwa z nich odwołują się do siebie nawzajem, ponieważ żaden licznik nie może osiągnąć zera. Przechowuj powiązanie tylko w jednym kierunku albo przechowuj nazwę zamiast obiektu.

Używaj RefCounted do danych: przedmiotów, wyników, rekordów. Używaj Node dla obiektów, które znajdują się w drzewie sceny.

challenge icon

Wyzwanie

Łatwy

Węzeł Wave przechowuje swoich przeciwników jako węzły podrzędne. Plik enemy.gd jest kompletny: Enemy.new("Goblin", 5) tworzy węzeł przeciwnika o nazwie Goblin i 5 punktach HP. Napisz trzy metody klasy Wave:

  • spawn(enemy_name, hp) dodaje nowego przeciwnika jako węzeł podrzędny. Jeśli istnieje już węzeł podrzędny o tej nazwie, wypisuje Orc is already here i niczego nie tworzy.
  • hit(enemy_name, damage) zmniejsza wartość hp tego przeciwnika i wypisuje Orc has 8 HP. Gdy HP wynosi 0 lub mniej, wypisuje Orc defeated i natychmiast usuwa przeciwnika na stałe: następne wywołanie alive() nie może go już uwzględniać. Jeśli przeciwnika o podanej nazwie nie ma, wypisuje No Orc here.
  • alive() zwraca liczbę pozostałych przeciwników.

Każdy węzeł musi zostać zwolniony: każdy wyciek pamięci przy zakończeniu powoduje niezaliczenie testu. Dostarczony kod dodaje falę do drzewa sceny, odczytuje liczbę kolejnych poleceń (spawn Goblin 5, hit Goblin 6, count) i wypisuje liczbę pozostałych przeciwników. Dla poleceń spawn Goblin 5, spawn Orc 12, hit Goblin 6, count, hit Goblin 1, spawn Orc 3, hit Orc 4 wypisuje:

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

Twój kod umieść w plikach wave.gd i enemy.gd. Plik main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

extends Node

func _ready():
	# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
	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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator GDScript online