This page replaces “howtoscenetree.png” and “howtoscenetree2.png” If you know them. Delete them. @export reigns supreme in Godot 4.
A Node
So you want to access the properties or functions of another Node?
In the same Scene
If you can see the node in the same scene as the one from which you are trying to access it. Use @export
class_name House
@export var door: Door
func _ready()
door.open()
Then assign the Door to the exported property.
In another Scene
If both scenes are siblings within the same parent scene. Say, there is a LightSwitch and a Light inside the same House, then you can use @export like you would if they were in the same scene.
If the target is not available in the same scene. But is hidden within a subscene, you may be able to use the parent scene as the communication relay.
class_name World
@export var house: House
@export var switch: Switch
func _ready() -> void:
switch.target = house.light
class_name House
@export var light: Light
class_name Switch
var target: Switchable
func _on_switch_toggled(enabled: bool) -> void:
target.enabled = enabled
Somewhere else entirely
If there is no scene hierarchy through which the objects can easily access each other. Consider using an Autoload as the relay. I prefer ID based structures for situations in which there are many of the same kind of thing. In other scenarios, simply having a property in an autoload you assign to, can work fine. (Like keeping a Global.player reference to the player object. Or the Interface.)
class_name Interactibles
var _interactibles: Dictionary[String, Interactible] = {} # ID : Object
func add_interactible(interactible: Interactible) -> void:
# Adds to the dictionary and performs any needed initialization.
func get_interactible(id: String) -> Interactible:
# Returns the object if it exists.
class_name Switch
@export var target_id: String
var target: Interactible:
get: return Interactibles.get_interactible(target_id)
func _on_switch_toggled(enabled: bool) -> void:
target.enabled = enabled
Dynamically created
When the object is dynamically created, then the easiest thing is to just keep the reference around instead of throwing it away.
class_name House
var front_door: Door
func _ready() -> void:
front_door = Door.new()
add_child(front_door
func _on_lever_activated() -> void:
front_door.open()
A Resource
So you want to access the properties of a Resource?
From a File (.tres, .res, etc.)
Loading a resource will return an instance of it. No matter how many times you load a resource, you will always get the same Instance. This is because each Resource File represents a specific Instance.
load("PlayerConfig.tres")
will always return the same resource.
class_name House
var house_config: HouseConfig = load("HouseConfig.tres")
# Alll Houses will have the same resource.
# No matter which House changes this resource.
# All Houses will access the same resource, and see the same changes.
When using @export to apply a Resource to a Class. You can use the “local to scene” toggle in the Resource itself. To automatically run the following code snipped, and thus get each house a Unique copy.
This is what the ‘local to scene’ setting actually does.
func _init() -> void:
if house_config.local_to_scene:
house_config = house_config.duplicate()
From a Node
Access the Resource as a member property.
class_name ResourceManipulator
@export var node_with_resource: Node
var the_resource: Resource = node_with_resource.the_resource
Shared between Nodes
The best way to access a Resource that is used in many different places. Is to save it as a file, and then load() it.
A File? A Class?
Not sure? Lets examine some options.
Static Things
To access const
and enum
properties of a Class Script. Give it a name.
class_name CarConstants
enum COLOR {BLUE, RED}
const SPEED: int = 100
class_name RaceCar
@export var color: CarConstants.COLOR
@export var speed: CarConstants.SPEED
Dynamic Things
Make a new instance of the named class.
class_name CarStats
enum COLOR {RED, BLUE}
var color: Color = COLOR.RED
const SPEED: int = 100
var speed: int = 100
class_name RaceCar
@export var speed_override: int = 500:
set(value):
speed_override = value
car_stats.speed = speed_override
var car_stats: CarStats = CarStats.new()
# This is unique to this specific car