Menu
CoddyTech

인자가 있는 시그널

Coddy GDScript 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 65개 중 38번째.

시그널은 값을 전달할 수 있습니다. 함수의 매개변수처럼 선언부에 값을 나열하세요.

signal damaged(amount: int, hp_left: int)
signal died

값을 같은 순서로 emit()에 전달합니다:

func take_damage(amount: int) -> void:
	hp = maxi(hp - amount, 0)
	damaged.emit(amount, hp)
	if hp == 0:
		died.emit()

연결된 함수는 값을 매개변수로 받으므로, 값마다 매개변수가 하나씩 필요합니다:

hero.damaged.connect(_on_hero_damaged)

func _on_hero_damaged(amount: int, hp_left: int) -> void:
	print("-%d HP, %d left" % [amount, hp_left])

선언의 타입은 값을 문서화합니다. GDScript는 신호를 발생시킬 때 이를 확인하지 않습니다. 불일치는 신호를 받는 함수에서 드러납니다. 매개변수 개수가 잘못된 함수이거나 값을 담을 수 없는 타입 지정 매개변수가 있는 경우, emit() 줄에서 오류가 발생하며 해당 함수는 실행되지 않습니다.

bind()는 방출된 값 뒤에 직접 지정한 값을 추가합니다. 그러면 하나의 메서드가 여러 영웅의 신호를 수신하면서도 어떤 영웅이 피해를 입었는지 알 수 있습니다.

ada.damaged.connect(_on_damaged.bind("Ada"))
bo.damaged.connect(_on_damaged.bind("Bo"))

func _on_damaged(amount: int, hp_left: int, who: String) -> void:
	print(who, " lost ", amount, " HP")

인수는 리스너에 필요한 데이터를 전달하므로, 리스너가 이미터에서 데이터를 읽을 필요가 없습니다. hero.died.connect(func(): print(hero.hp))처럼 이미터 객체 자체를 사용하는 람다를 연결하지 마세요. 람다가 hero를 계속 유지하고, hero는 람다를 계속 유지하므로 둘 다 해제되지 않으며, 프로그램이 종료될 때 Godot은 누수된 인스턴스가 있다고 보고합니다.

challenge icon

챌린지

쉬움

지갑은 숫자를 전달하는 시그널로 모든 변경 사항을 알립니다. Wallet에서 두 시그널에 매개변수를 추가하고 두 메서드를 작성하세요.

  • balance_changed(old_balance: int, new_balance: int)와 purchase_failed(price: int, missing: int)
  • add(amount)는 코인을 추가하고 변경 전후의 잔액을 담아 balance_changed를 발생시킵니다.
  • buy(price): 잔액이 충분하면 가격만큼 차감하고 balance_changed를 발생시킵니다. 그렇지 않으면 아무것도 변경하지 않고 가격과 부족한 코인의 수를 담아 purchase_failed를 발생시킵니다.

제공된 코드는 각 시그널을 하나의 함수에 연결하고, 이어지는 명령의 개수를 읽은 다음 각 명령(add 20, buy 15)을 실행하고 마지막에 남은 코인을 출력합니다. add 20, buy 15, buy 10, add 5, buy 10을 입력하면 다음을 출력합니다.

Balance: 0 -> 20
Balance: 20 -> 5
Cannot buy for 10: 5 coins missing
Balance: 5 -> 10
Balance: 10 -> 0
Coins left: 0

코드는 wallet.gd에 작성하세요. main.gd에는 제공된 입력/출력 코드가 있으며 수정할 수 없습니다.

직접 해보기

extends Node

func _ready():
	# 제공된 입출력 코드: 그대로 유지하세요
	var wallet := Wallet.new()
	wallet.balance_changed.connect(_on_balance_changed)
	wallet.purchase_failed.connect(_on_purchase_failed)
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "add":
			wallet.add(int(parts[1]))
		else:
			wallet.buy(int(parts[1]))
	print("Coins left: ", wallet.balance)

func _on_balance_changed(old_balance: int, new_balance: int) -> void:
	print("Balance: %d -> %d" % [old_balance, new_balance])

func _on_purchase_failed(price: int, missing: int) -> void:
	print("Cannot buy for %d: %d coins missing" % [price, missing])
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 GDScript 컴파일러