Menu
CoddyTech

RefCounted ve Node Karşılaştırması

Coddy'nin GDScript Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 43 / 65.

Her nesne, serbest bırakılana kadar bellek kullanır. RefCounted ve Node farklı şekillerde serbest bırakılır.

Bir RefCounted nesnesi, ona başvuran değişkenleri, dizileri ve nesneleri sayar. Sayı sıfıra düştüğünde Godot nesneyi kendi başına serbest bırakır. Special Methods bölümündeki NOTIFICATION_PREDELETE, bu anı gösterir:

# 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()          # Önce Note written, ardından Note freed
	print("Back in _ready")

Tek referans note olduğu için, write() sona erer ermez not serbest bırakılır.

Bir Node sayılmaz. Sahne ağacındaki bir düğüm, üst öğesiyle birlikte serbest bırakılır ve oyun sona erdiğinde ağacın tamamı serbest bırakılır. Ağaçtan çıkardığınız veya ağaca hiç eklemediğiniz bir düğümü sizin serbest bırakmanız gerekir:

crate.free()         # tüm alt öğeleriyle birlikte hemen serbest bırakılır
crate.queue_free()   # geçerli karenin sonunda serbest bırakılır

free() sonrasında düğüm artık yoktur: is_instance_valid(crate), false döndürür ve üzerinde bir yöntem çağırmak hatadır. Bu karede başka kodlar düğümü hâlâ kullanıyor olabileceğinden queue_free() güvenli seçimdir; ancak bu kare sona erene kadar düğüm ağaçta kalır ve get_child_count() içinde sayılmaya devam eder.

Hiç serbest bırakılmayan bir düğüm, bir bellek sızıntısıdır: program sona erdiğinde Godot, "ObjectDB instances were leaked at exit" bildirimini verir. İki RefCounted nesnesi birbirine başvurduğunda onlar da sızıntı yapar, çünkü hiçbirinin sayacı sıfıra ulaşamaz. Bağlantıyı yalnızca tek yönde saklayın ya da nesne yerine bir ad saklayın.

Veriler için RefCounted kullan: öğeler, puanlar, kayıtlar. Sahne ağacında yaşayan şeyler için Node kullan.

challenge icon

Görev

Kolay

Bir Wave düğümü, düşmanlarını alt düğümleri olarak tutar. enemy.gd tamamlanmıştır: Enemy.new("Goblin", 5), 5 HP'ye sahip ve Goblin adlı bir düşman düğümü oluşturur. Wave için üç yöntemi yaz:

  • spawn(enemy_name, hp) yeni bir düşmanı alt düğüm olarak ekler. Bu ada sahip bir alt düğüm varsa Orc is already here yazdırır ve hiçbir şey oluşturmaz.
  • hit(enemy_name, damage) o düşmanın hp değerini düşürür ve Orc has 8 HP yazdırır. HP değeri 0 veya daha az olduğunda Orc defeated yazdırır ve düşmanı hemen ve kalıcı olarak kaldırır: sonraki alive() çağrısı onu saymamalıdır. Mevcut olmayan bir ad için No Orc here yazdırılır.
  • alive() geriye kalan düşman sayısını döndürür.

Her düğüm serbest bırakılmalıdır: program sona erdiğinde herhangi bir bellek sızıntısı testi başarısız kılar. Sağlanan kod dalga düğümünü sahne ağacına ekler, ardından kaç komut geleceğini okur (spawn Goblin 5, hit Goblin 6, count) ve geriye kalan düşmanları yazdırır. spawn Goblin 5, spawn Orc 12, hit Goblin 6, count, hit Goblin 1, spawn Orc 3, hit Orc 4 komutları için şu çıktıyı verir:

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

Kodunu wave.gd ve enemy.gd dosyalarına yaz. main.gd, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

extends Node

func _ready():
	# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
	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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online GDScript derleyicisi