Menu
CoddyTech

싱글턴 패턴

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

싱글턴 패턴은 클래스에 객체가 정확히 하나만 있도록 보장하고 모든 스크립트가 그 객체에 접근할 수 있는 하나의 방법을 제공합니다. 게임에 하나만 있는 것, 예를 들어 설정, 저장 시스템, 점수 관리에 사용하세요.

GDScript에서 static var는 단일 객체를 보유하고, static func는 누군가 처음 요청할 때 객체를 생성합니다:

# game_settings.gd
class_name GameSettings
extends RefCounted

static var _instance: GameSettings = null

var volume := 50

static func get_instance() -> GameSettings:
	if _instance == null:
		_instance = GameSettings.new()
		print("Creating settings")
	return _instance

_instance는 객체가 아니라 클래스에 속하므로 모든 스크립트에서 같은 변수를 봅니다. 첫 번째 호출에서는 변수가 비어 있는 것을 확인하고 객체를 생성하며, 이후의 모든 호출은 같은 객체를 반환합니다.

# main.gd
var a := GameSettings.get_instance()
var b := GameSettings.get_instance()
a.volume = 80
print(b.volume)
print(a == b)
Creating settings
80
true

a와 b는 하나의 객체를 참조하는 두 변수이므로, a를 통해 변경한 내용이 b에도 반영됩니다. 객체의 경우 양쪽이 동일한 객체일 때만 ==가 true입니다.

GDScript에서는 _init()을 비공개로 만들 수 없으므로, 스크립트가 GameSettings.new()를 호출해 두 번째 객체를 얻는 것을 막을 방법이 없습니다. _instance의 밑줄과 get_instance() 메서드는 서로 간의 약속입니다. 스크립트는 객체를 요청할 뿐, 직접 생성하지 않습니다.

Godot 프로젝트에서 공유 객체 하나를 얻는 일반적인 방법은 오토로드입니다. Project Settings에서 등록하는 스크립트로, Godot가 게임이 시작될 때 한 번 생성하고 모든 스크립트에서 이름으로 사용할 수 있게 해 줍니다. 이는 Godot가 관리해 주는 싱글톤입니다. 오토로드는 에디터에서 설정하므로, 여기의 과제에서는 static var를 사용해 코드로 이 패턴을 구현합니다.

challenge icon

챌린지

쉬움

게임의 모든 코인은 하나의 공유 점수에 더해집니다. ScoreManager를 싱글턴으로 만드세요.

  • 하나의 객체를 static var에 저장합니다.
  • static func get_instance()는 객체를 반환하며, 첫 호출 시 객체를 생성합니다. 생성 직후 Score manager created를 출력합니다.
  • add_points(points)는 score에 점수를 더합니다.

coin.gd에서 collect()는 ScoreManager.get_instance()를 통해 코인의 value를 점수에 더합니다.

제공된 코드는 이어지는 이벤트의 개수를 읽은 다음, 한 줄에 하나씩 이벤트를 읽습니다. coin VALUE는 새 코인을 수집하고, bonus POINTS는 점수를 바로 더합니다. 각 이벤트가 끝날 때마다 점수를 출력하고, 마지막에는 get_instance()를 두 번 호출했을 때 같은 객체를 반환하는지 출력합니다. coin 5와 bonus 20을 입력하면 출력은 다음과 같습니다.

Score manager created
Score: 5
Score: 25
Same object: true

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

직접 해보기

extends Node

func _ready():
	# 제공된 입출력 코드: 그대로 두세요
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "coin":
			Coin.new(int(parts[1])).collect()
		elif parts[0] == "bonus":
			ScoreManager.get_instance().add_points(int(parts[1]))
		print("Score: %d" % ScoreManager.get_instance().score)
	print("Same object: %s" % (ScoreManager.get_instance() == ScoreManager.get_instance()))
quiz icon실력 점검

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

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

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