Godot 4.2.1实例化场景后调用set_texture报错:节点属性为Null
我有一个继承自Area2D的场景DragonSelector,场景内包含名为DragonSprite的Sprite2D节点,相关代码如下:
DragonSelector.gd
class_name DragonSelector extends Area2D @onready var dragon_sprite = $DragonSprite func _ready(): pass func _process(delta): pass func set_texture(dragon_texture: Texture): dragon_sprite.Texture = dragon_texture
我在Main场景中实例化该场景并尝试运行时设置纹理,代码如下:
Main.gd
class_name Main extends Node2D var dragon_selector_scene = preload("res://dragon_selector/dragon_selector.tscn") func _ready(): var dragon_selector_instance = dragon_selector_scene.instantiate() var texture = preload("res://dragon/flying_dragon-gold.png") dragon_selector_instance.set_texture(texture) add_child(dragon_selector_instance) dragon_selector_instance.position = Vector2(100, 100) func _process(delta): pass
运行后触发错误:Invalid set index 'Texture' (on base: 'Nil') with value of type 'CompressedTexture2D',错误定位到set_texture方法中的纹理赋值行。
为验证纹理路径正确,我修改了DragonSelector.gd的set_texture方法,直接在方法内加载纹理,修改后运行正常:
func set_texture(dragon_texture: Texture): dragon_sprite.Texture = preload("res://dragon/flying_dragon-gold.png") #dragon_sprite.Texture = dragon_texture
使用Godot 4.2.1版本,寻求问题的修正方案。
问题根源
@onready修饰的变量要等到节点被添加到场景树后才会完成初始化。你当前的代码是先调用set_texture,再执行add_child,此时dragon_selector_instance还未进入场景树,dragon_sprite处于Nil状态,因此赋值操作会报错。而直接在set_texture内预加载纹理时,实际执行赋值的时机可能已经触发了@onready(节点已入树),所以能正常运行。
另外注意:Godot 4中节点属性采用小写驼峰命名,Texture应改为texture,这是容易忽略的规范问题。
可行解决方式
方式一:调整调用顺序,先添加节点再设置纹理
修改Main.gd的_ready方法,先将实例添加到场景树,再调用set_texture:
func _ready(): var dragon_selector_instance = dragon_selector_scene.instantiate() var texture = preload("res://dragon/flying_dragon-gold.png") add_child(dragon_selector_instance) # 先加入场景树,触发@onready初始化 dragon_selector_instance.set_texture(texture) # 再设置纹理 dragon_selector_instance.position = Vector2(100, 100)
方式二:手动初始化节点引用,不依赖@onready
如果需要在节点入树前设置纹理,可以修改DragonSelector.gd,手动确保dragon_sprite不为Nil:
class_name DragonSelector extends Area2D var dragon_sprite: Sprite2D func _ready(): dragon_sprite = $DragonSprite func set_texture(dragon_texture: Texture): # 若未初始化,手动获取节点 if not dragon_sprite: dragon_sprite = $DragonSprite dragon_sprite.texture = dragon_texture # 改用小写texture
内容的提问来源于stack exchange,提问作者Yoav

