creating-nodes-and-scene-instances

Creating nodes and scene instances

This guide recaps how to create instances of nodes and scenes.

We’ll go over:

If we compare programming to cooking and the Godot engine to a chef:

Both scripts and scene files are templates from which you make reproductions.

The new() and instance() functions

There are two functions to respectively create a node and a scene instance: new() and instance().

You use new() if you want an instance of a script, and instance() if you want an instance of a scene.

# Instancing one label node.
var label := Label.new()

# Instancing a scene from a scene file. Notice how we need to load the file
# first.
var my_scene_instance := preload("MyScene.tscn").instance()

Note: while instance() is only for scenes, new() is also used for many more types than nodes. You’ll learn about that much later in the course.

The .new() function

When you create a specific node type, you use Object.new(). It’s a function that exists on scripts and built-in object types (nodes are specific kinds of objects) in Godot.

Below, we use the new() function to create three buttons programmatically.

var buttons_texts := ["ok", "cancel", "read more"]

func create_buttons() -> void:
    for text in buttons_texts:
        var button := Button.new()
        button.text = text
        add_child(button)

When Godot reads the line var button := Button.new():

  1. It uses the Button recipe.
  2. It creates a reproduction of the Button.

When you add a node in the editor with the Add Node button in the Scene dock (or by pressing Ctrl+A), behind the scenes, Godot calls .new().

The instance() function

When you create an instance of a scene, you use .instance(). For example:

var pickup_heart_scene := preload("PickupHeart.tscn")

func create_heart_pickup() -> void:
    var heart_pickup := pickup_heart_scene.instance()
    add_child(heart_pickup)

When Godot reads the line var heart_pickup := pickup_heart_scene.instance():

  1. It uses the pickup_heart_scene menu.
  2. It reproduces the scene as you designed it in the editor.

When you open a scene file in the editor, or add a scene with the Add Scene Instance button in the Scene eock (or press Ctrl+Shift+A), Godot calls .instance() behind the scenes.

The add_child() function

Once you have an instance, whether you used instance() or new(), you will want to add it to the scene tree. A node that isn’t in the scene tree isn’t doing anything.

You do this with add_child():

const pickup_heart_scene := preload("PickupHeart.tscn")

func create_pickup_heart() -> void:
    # We create a Label node.
    var label := Label.new()
    label.text = "health"

    # We instantiate the PickupHeart scene.
    var heart_pickup := pickup_heart_scene.instance()
    # We add the Label as a child of the scene instance.
    heart_pickup.add_child(label)

    # We add the scene instance as a child of the node with this script.
    add_child(heart_pickup)

The code above could produce a node tree like the one below:

When should you create nodes in code or in the editor

In general, it’s better to create nodes and scenes from the editor. You get a better visual preview and can tweak properties using the Inspector.

But consider the following situations:

Creating nodes using the editor in these examples is difficult because you do not know yet what you will need.

That is when you will favor creating nodes using code.

How do we load Scene Files, Scripts, or Resources?

Godot lets us load files by passing the path to a file as an argument to the preload() function.

When you run a scene, this function loads the file before displaying anything on the screen.

You can copy a file’s absolute path from the FileSystem dock by right-clicking on the file and selecting Copy Path from the context menu.

You can also use the shortcut Ctrl+Shift+C to do it even faster.

For example:

var rock_scene := preload("res://common/rocks/Rock.tscn")

Using relative file paths with preload()

We recommend using relative paths whenever possible because it makes moving files around your Godot projects easier.

For example, if the scene you want to load is in the same directory as the script you’re using, you can write the path like this:

var rock_scene := preload("Rock.tscn")

When you open a resource in the editor, Godot loads it with the same mechanism behind the scenes.

Using the load() function instead of preload()

If you do not know the path to a resource in advance, you can’t use the preload() function. Instead, you’ll use the load() function.

For example:

var color := "red"
var direction := "west"

var arrow_texture := load("res://common/arrows/arrow_" + direction + "_" + color + ".png")

The above code would load an image called res://common/arrows/arrow_west_red.png, but we could dynamically change the color and direction to load different files.

The load() function has important differences with preload():

  1. Paths are not checked by the editor. If you load a file that does not exist by calling load(), the editor cannot know in advance. Using preload(), if you use a wrong path, the editor will give you an error immediately.
  2. Paths cannot be relative. The function load() only accepts absolute paths.