Beginner mental model for Godot C#, scenes, and PackedScenes

Godot Version

4.5

Question

I’m just learning Godot and using C# (I’ve worked in C# for a decade, so y’know), and I’m trying to understand Godot’s mental model. Right now, I’m trying to understand what a PackedScene represents, and how it differs from a Scene, and I think I’m misunderstanding Scenes and Nodes in general.

So I think a Scene is like a class definition for Nodes, because you can add instances of a Scene as a Node to other scenes. This implies I should be able to new() a Scene instance and get a handle to something I can add to the Scene tree… but that’s not true. If I want to dynamically add an instance of a Scene, I have to use:

MyPackedScene = ResourceLoader.Load<PackedScene>("res://scenes/my-scene.tscn");
MyScene sceneInstance = MyPackedScene.Instantiate<MyScene>();

…but I don’t know what the difference is between that and just calling:

MyScene sceneInstance = new MyScene();

Both allow me to AddChild(sceneInstance) without errors, but only the first actually does anything.

So my question is: what does a PackedScene represent, and how is that different from what a Scene class definition represents? Why is it that I can get an instance of MyScene using either approach, but they have different behaviors?

Thanks!

Even though they don’t answer your question directly, I’d suggest you reading through these:

Thinking of Scenes as Classes is close, but not a perfect analogy, which breaks exactly with your example.
Let me quote the docs:

When you organize nodes in a tree, like our character, we call this construct a scene. Once saved, scenes work like new node types in the editor, where you can add them as a child of an existing node. In that case, the instance of the scene appears as a single node with its internals hidden.

Calling new() only creates a Class item, which if it extends a Node type, will just be a single Node with default values that can be added to the tree.
Calling instantiate() creates a whole tree structure of nodes that you saved as a PackedScene. It can also be just one Node, but can also be 100 Nodes.

I did this simple test for showcase. I created a SceneTest class script and created a simple PackedScene that I saved to a file, with just a root node and a child.

And then in the MainScene’s _ready() I instantiated the scene and created a new class object. You can see on the right side, in the Remote tab at runtime, the first call recreated the whole tree with a child, whereas the second call created only the root Node without the children.


I think you might not understand the design philosophy behind Godot’s “Node” and “Resource”. Since this involves extensive Godot knowledge, I can’t explain it in great detail here. I recommend searching for Godot tutorials to grasp some fundamental concepts, which will help you use Godot more effectively.

Let me briefly answer your questions:

1. Question: “What does a PackedScene represent, and how is that different from what a Scene class definition represents?”

Knowledge points: “Factory Pattern”, “Resource”

Answer:

a. “PackedScene” is a factory class for instantiating “Node”. It not only creates instances of Node classes but also sets values for all exported properties of the Node instance, ensuring the resulting Node instance no longer has just the default values from code.

b. The “PackedScene” class is a subclass of “Resource”, so it can be loaded from disk using “ResourceLoader.Load”.

c. Open a “*.tscn” file in plain text. You’ll see how the PackedScene instance sets which property values and how it creates Node class instances.

2. Question: “Why is it that I can get an instance of MyScene using either approach, but they have different behaviors?”

Answer:

Using ResourceLoader.Load deserializes a “PackedScene” instance from disk, then “MyPackedScene.Instantiate()” instantiates a Node class instance according to the requirements specified in the “*.tscn” file.

Conversely, using “new MyScene()” only gives you a class instance with default values, without any serialized property overrides from the scene file.


Key Distinction: PackedScene.instantiate() creates nodes with serialized state from disk, while new() creates nodes with code-defined default values only.

Since you haven’t yet mastered the concepts related to “Node”, I must add a clarification to avoid any misunderstanding:

Although PackedScene instantiation returns a “Node” instance, the Node class itself is a tree structure—it can add child nodes via add_child(), meaning Node inherently acts as a container. Therefore, PackedScene doesn’t just instantiate a single Node; it instantiates the entire node hierarchy. PackedScene returns the root node of the scene.

1 Like

If I understand what you’re both telling me, then my fundamental misunderstanding was in equating the root Node of a Scene with the Scene itself. If they’re distinct, then my partial class MyScene : Node2D definition is extending only the root Node, so I only get an instance of that root Node by calling new MyScene(), and the only way to get an instance of the entire Scene tree is through PackedScene.Instantiate(). Is that correct?

Thank you both!

Correct

1 Like