Accessing child node's property using a String

Godot Version

4.2.1

Question

Hello!

I’m trying to create a dictionary of properties of multiple child nodes that I could use to set those properties.
Simplified example:

extends Node3D

@onready var child_node_1 = %Node1
@onready var child_node_2 = %Node2

const SETTINGS: Dictionary = {
	"child_node_1:position" : Vector3(1.0, 1.0, 1.0),
	"child_node_2:position" : Vector3(2.0, 2.0, 2.0),
}

func apply_settings() -> void:
	for key in SETTINGS.keys():
		set(key, SETTINGS[key])

The point is that I’d like to access properties of child nodes using a String, like: "child_node_1:position" but it doesn’t work.
get("child_node_1:position") returns null. Same for get("child_node_1/position")

( get("child_node_1") works, so the reference to the node is correct )

Is there a way to make this work without actually adding a reference of the child node to the SETTINGS dictionary?

Object.set() only works with properties of the same object. It has no knowledge about the scene tree or access to any other node.

You’ll need to use Node.get_node_and_resource() for what you want to achieve.

Something like:

extends Node


func _ready() -> void:
	set_value('CollisionShape2D:shape:radius', 200)
	set_value('Sprite2D:position', Vector2(10, 10))
	set_value('CollisionShape2D2:shape', CapsuleShape2D.new())


func set_value(p:NodePath, value:Variant) -> void:
	var result = get_node_and_resource(p)
	var node = result[0]
	var resource = result[1]
	var property = result[2].get_subname(result[2].get_subname_count() - 1) if result[2] else null
	if node:
		if property:
			if resource:
				# If we have a property and a resource then we need to set the property to that resource
				resource.set(property, value)
			else:
				# If we don't have a resource then the property is of that node
				node.set(property, value)
		elif resource:
			# If we have a resource and no property then we are changing
			# the resource of the node's property itself
			property = p.get_subname(p.get_subname_count() - 1)
			node.set(property, value)

I’ve only tested with a couple NodePaths so you may need to tweak the code to get a correct result

1 Like

This will work, get_node_and_resource() is more or less what I was looking for. Thank you!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.