SingletonNode
SingletonNode is a helper base class that guarantees a single active instance per script.
If another instance of the same script enters the scene tree, the duplicate is freed automatically.
It covers two usage patterns:
- Scene-based — the node lives as a child of a scene and is destroyed when that scene exits.
- Manual root — the node is created from code, mounted on
root, and persists across scene changes.
Installation
Section titled “Installation”- Download
ss-gameforge-singletonfrom the releases page. - Copy
addons/ss-gameforge-singleton/into your project’sres://addons/. - Enable ss-gameforge-singleton in Project Settings → Plugins.
Key API
Section titled “Key API”| Method | Description |
|---|---|
SingletonNode.get_instance_for(script) | Returns the active instance for a given script class. |
SingletonNode.ensure_for(script, root, name) | Creates and adds the instance if it doesn’t exist yet. |
is_active_instance() | Returns true if this node is the current active singleton. |
Usage — scene-based
Section titled “Usage — scene-based”Use this when the singleton only makes sense inside a specific scene and should be destroyed when leaving it: a boss fight director, a puzzle controller, a run session manager.
Extend SingletonNode and expose a typed static accessor:
extends SingletonNodeclass_name BossFightDirector
static var i: BossFightDirector: get: return SingletonNode.get_instance_for(BossFightDirector) as BossFightDirector
var phase := 1
func next_phase() -> int: phase += 1 return phaseAdd the node as a child of the boss fight scene. If a duplicate enters the tree it is freed automatically.
# safe from anywhere — returns null if not in the boss sceneif BossFightDirector.i: BossFightDirector.i.next_phase()Usage — manual root (persistent)
Section titled “Usage — manual root (persistent)”Use this when the singleton must persist across scene changes but you want to control exactly when it is created — a save service created only after session start, a network service only when connected.
extends SingletonNodeclass_name SaveService
static var i: SaveService: get: return SingletonNode.get_instance_for(SaveService) as SaveService
func save_game() -> void: print("[SaveService] Saving...")Create it from code and mount it on root:
func _ready() -> void: SingletonNode.ensure_for(SaveService, get_tree().root, "SaveService")The node now lives under root, survives change_scene_to_*, and is accessible via SaveService.i from anywhere.