Reputation: 185
I have a game_board
scene with only a root Node2D
and no children.
I wish to programmatically create playing slots on this board.
These slots are to be instantiated from a separate scene file.
Since GDScript doesn't have a constructor, I wrote a static constructor initializing the required members (currently just a slot_id: int
)
game_board.gd
extends Node2D
const play_slot_scene = preload("res://scenes/PlaySlot/play_slot.tscn")
func _ready():
if not play_slot_scene.can_instantiate():
push_error("Couldn't instantiate play slot")
var firstSlot: PlaySlot = play_slot_scene.instantiate()
firstSlot.slot_id = 0;
add_child(firstSlot)
for n in range(1,7):
var nextChild = firstSlot.constructor(n)
add_child(nextChild)
play_slot.gd
class_name PlaySlot
extends Node2D
const self_scene = preload("res://scenes/PlaySlot/play_slot.tscn")
@export var slot_id: int
static func constructor(id: int = 0)-> PlaySlot:
var obj = self_scene.instantiate()
obj.slot_id = id
return obj
The code errors out at var firstSlot: PlaySlot = play_slot_scene.instantiate()
because firstSlot is a Node2d
obj (not an instance of PlaySlot
class).
If I remove the static typing, the next line fails because slot_id
does not exist on Node2D
.
How do I instantiate these nodes with the right class? TIA
Upvotes: 0
Views: 5792
Reputation: 185
At the _ready()
function in the game board, instanced child scenes have not bound to the attached script.
In essence, the instanced node is Node2D
and can't bind slot_id
A better way do achieve what I was trying is to simply use the static constructor()
. This avoids preloading the PackedScene
.
game_board.gd
extends Node2D
@onready var play_slot_grid: GridContainer = %PlaySlotGrid
func _ready():
generate_play_slots()
func generate_play_slots():
for i in range(0,9):
var nextChild: PlaySlot = PlaySlot.constructor(i)
nextChild.name = "PlaySlot" + str(i)
nextChild.add_to_group("PlaySlots")
play_slot_grid.add_child(nextChild)
play_slot.gd
class_name PlaySlot
extends Control
# Nodes
const self_scene = preload("res://scenes/PlaySlot/play_slot.tscn")
# Members
@export var slot_id: int
static func constructor(id: int = 0)-> PlaySlot:
var obj = self_scene.instantiate()
obj.slot_id = id
return obj
PackedScene
However, if you must do things using a PackedScene
, you need to have an instance ready with instantiate()
game_board.gd
extends Node2D
@onready var play_slot = preload("res://scenes/PlaySlot/play_slot.tscn").instantiate()
func _ready():
# Doesn't complain because play_slot is not Node2D here
play_slot.slot_id = 123
Upvotes: 1