Singleton Pattern
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 46 of 65.
The Singleton pattern makes sure a class has exactly one object and gives every script one way to reach it. Use it for things a game has only one of: the settings, the save system, the score keeper.
In GDScript, a static var holds the single object, and a static func creates it the first time someone asks for it:
# 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 belongs to the class, not to an object, so every script sees the same variable. The first call finds it empty and creates the object; every later call returns that same object.
# main.gd
var a := GameSettings.get_instance()
var b := GameSettings.get_instance()
a.volume = 80
print(b.volume)
print(a == b)Creating settings
80
truea and b are two variables holding one object, so the change made through a shows through b. For objects, == is true only when both sides are the same object.
GDScript cannot make _init() private, so nothing stops a script from calling GameSettings.new() and getting a second object. The underscore in _instance and the get_instance() method are the agreement: scripts ask for the object, they never create it.
In a Godot project, the usual way to get one shared object is an autoload: a script you register in Project Settings, which Godot creates once when the game starts and makes available by name in every script. It is a Singleton that Godot manages for you. Autoloads are set up in the editor, so the challenges here build the pattern in code with static var.
Challenge
EasyEvery coin in a game adds to one shared score. Make ScoreManager a Singleton:
- A
static varholds the single object. static func get_instance()returns it, creating it on the first call. Right after creating it, it printsScore manager created.add_points(points)adds toscore.
In coin.gd, collect() adds the coin's value to the score through ScoreManager.get_instance().
The supplied code reads how many events follow, then one event per line: coin VALUE collects a new coin, bonus POINTS adds points directly. After each event it prints the score, and at the end whether two calls of get_instance() return the same object. For coin 5 and bonus 20 the output is:
Score manager created
Score: 5
Score: 25
Same object: trueYour code goes in score_manager.gd and coin.gd. main.gd holds the supplied input/output code and cannot be edited.
Try it yourself
extends Node
func _ready():
# Supplied input/output code: keep it as it is
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()))
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe self KeywordMethodsPropertiesConstructor (_init)Recap - Simple Calculator4Polymorphism
Method Overriding RevisitedDuck TypingAbstract Classes and MethodsInterface DesignRecap - Shape Calculator2Class Properties
Instance vs Static VariablesStatic FunctionsProperty SettersProperty GettersPrivate by ConventionRecap - Bank Account Manager5Encapsulation
Public and Private MembersValidation with SettersInformation HidingRead-Only PropertiesRecap - Student Records System8Advanced OOP Concepts
Composition vs InheritanceInner ClassesNodes as ComponentsRefCounted vs NodeEnums in Classes11Project: Library Management
Project OverviewBook and User Classes3Inheritance
Basic InheritanceThe super KeywordMethod OverridingInheritance ChainsType Checks with isRecap - Employee Hierarchy6Special Methods
Virtual Methods IntroductionThe _to_string MethodCustom IteratorsRecap - Custom List9Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy PatternPractice on your own: Online GDScript compiler