Menu
CoddyTech

Patron Singleton

Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 46 sur 65.

Le modèle Singleton garantit qu’une classe possède exactement un objet et offre à chaque script un moyen d’y accéder. Utilise-le pour les éléments dont un jeu ne possède qu’un seul exemplaire : les paramètres, le système de sauvegarde, le gestionnaire de score.

En GDScript, un static var conserve l’unique objet, et une static func le crée la première fois que quelqu’un le demande :

# 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 appartient à la classe, et non à un objet, donc tous les scripts voient la même variable. Le premier appel la trouve vide et crée l’objet ; chaque appel suivant renvoie ce même objet.

# 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 et b sont deux variables qui contiennent un même objet ; la modification effectuée via a est donc visible via b. Pour les objets, == vaut true uniquement lorsque les deux côtés désignent le même objet.

GDScript ne peut pas rendre _init() privé, donc rien n’empêche un script d’appeler GameSettings.new() et d’obtenir un deuxième objet. Le trait de soulignement dans _instance et la méthode get_instance() constituent la convention : les scripts demandent l’objet, ils ne le créent jamais.

Dans un projet Godot, la méthode habituelle pour obtenir un objet partagé consiste à utiliser un autoload : un script que tu enregistres dans les paramètres du projet, que Godot crée une seule fois au démarrage du jeu et qu’il rend accessible par son nom dans chaque script. C’est un Singleton que Godot gère pour toi. Les autoloads se configurent dans l’éditeur ; les défis présentés ici mettent donc en place le modèle en code avec static var.

challenge icon

Défi

Facile

Chaque pièce d'un jeu contribue à un score commun. Faites de ScoreManager un Singleton :

  • Un static var contient l'unique objet.
  • static func get_instance() le renvoie, en le créant lors du premier appel. Juste après l'avoir créé, il affiche Score manager created.
  • add_points(points) ajoute des points à score.

Dans coin.gd, collect() ajoute la value de la pièce au score via ScoreManager.get_instance().

Le code fourni lit le nombre d'événements à venir, puis un événement par ligne : coin VALUE collecte une nouvelle pièce, bonus POINTS ajoute directement des points. Après chaque événement, il affiche le score et, à la fin, indique si deux appels de get_instance() renvoient le même objet. Pour coin 5 et bonus 20, la sortie est :

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

Votre code va dans score_manager.gd et coin.gd. main.gd contient le code d'entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

extends Node

func _ready():
	# Code d'entrée/sortie fourni : conservez-le tel quel
	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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur GDScript en ligne