如何使用构造函数动态实例化场景中的节点?

问题描述 投票:0回答:1

我有一个

game_board
场景,只有根
Node2D
并且没有子节点。 我希望以编程方式在该板上创建游戏老虎机。 这些槽将从单独的场景文件实例化。

由于 GDScript 没有构造函数,我编写了一个静态构造函数来初始化所需的成员(目前只是一个

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

代码在

var firstSlot: PlaySlot = play_slot_scene.instantiate()
处出错,因为firstSlot是一个
Node2d
对象(不是
PlaySlot
类的实例)。

如果我删除静态类型,下一行将失败,因为

slot_id
不存在于
Node2D
上。

如何使用正确的类实例化这些节点? TIA

godot gdscript godot4
1个回答
0
投票

在游戏板的

_ready()
功能中,实例化的子场景尚未绑定到附加的脚本。 本质上,实例化节点是
Node2D
并且无法绑定
slot_id

正确的方法

实现我想要的效果的更好方法是简单地使用

static constructor()
。这可以避免预加载
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

但是,如果您必须使用

PackedScene
执行操作,则需要准备一个带有
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
© www.soinside.com 2019 - 2024. All rights reserved.