Howdy folks!

I've been trying to access a child node and I don't know what I'm doing wrong here. The main-scene is called "Main", which is a base-node of the type Node. "Main" has a child-node called "_Data", which is of the type Node aswell. Here is a picture:

Main.cs is trying to get a public string from Data.cs. The error I'm getting is: 'Node' does not contain a defintion for 'title' and no extension method 'title' accepting a first argument of type 'Node' could be found (are you missing a using_ directive or an assembly refernce?)

c# is the first statically typed language I'm learning and I can't grasp the error here...

Also: What's the 'intended' way for doing global code, which holds game-state relevant data, in c#?

I think the problem is that you need to cast data to a _Data class. As explained in the Static Typing section of this article from the Godot devlog. So in theory what you need to do is change line 16 to either data = (_Data)GetNode("_Data"); or data = (Node)GetNode("_Data"). You will also need to change line 6 to private _Data data; if you need to cast to a _Data class.

The error message is trying to tell you that the class Node does not have a definition (meaning a variable defined in it's code) named title and there is no extension method (in C# you can make variables and define how they are their set/get, and that's what it's meaning by extension method. This article from Microsoft shows what I'm talking about.) named title either. Then it's basically asking you if you are sure that you are using the correct object/extension/class/reference.


I have no idea on how global code (singletons/autoloads/etc) work in Godot for C#. In theory you may be able to add a autoload script in the Godot editor, and then just use GetNode to retrieve it, though it's possible there is another way to go about it.

(I should mention that I've never used C# in Godot, but I have used C# before, so I'm going off my general C# knowledge. It is entirely possible my answer is completely off :sweat_smile: )

Thank you, casting to _Data works perfectly!

I tried casting to Node before, but I thought I wouldn't have to, because GetNode() returns Node. I guess it has to be of the type _Data because it just inherits from Node and is therefore a "different" class, right? Because the variables title, version and _debug are not added to Node directly, but to _Data ?

Regarding AutoLoads: I assume that what I did is basically what AutoLoads do, adding a node of the, in the project-settings configured, script. But I don't see an advantage with this over manually creating a node when using c#. In GDScript the class would be easily accessible by MyAutoload.member in every other script, but in c# you have to use GetNode() either way. Am I assuming this right?

You're welcome, I'm glad it works (I was not totally sure it would if I'm being honest). I'll try to answer your other questions.

[...] I guess it has to be type _Data because it just inherits from Node and is therefore a "different" class, right?

Yup! Because _Data extends Node you cannot access any of the variables and functions without casting. This is all because of polymorphism! Here is an article that explains polymorphism (if you are curious).


As far as autoloads go, yes and no.

When you mark a script as a singleton/autoload in Godot through the editor, what it does is creates a node with your script attached that exists outside the scene tree. The biggest reason you want your node (with your script) outside of the scene tree is so when you change scenes the data is all still there.

In GDScript you still have to call get_node, exactly the same as C#'s GetNode. For example, in one of my games I use a singleton/autoload for holding all of the input and graphics options in the game. In GDScript, I call get_node("root/Global_singleton") and that returns my global singleton node (I called my singleton/autoload 'Global_singleton' in this case. In your case it may be something different, so you'd need to change the name from 'Global_singleton' to the name you put in the editor). In C# it should be (Global_singleton)GetNode("root/Global_singleton") if singletons/autoloads work the same way as they do in GDScript.

All of that said, it is entirely possible to make a global data node without using a singleton/autoload structure. It would be a lot more work, but it is doable. I should also mention that if you do not plan to change scenes, then having the data the way you do currently will work fine, but when you change scenes the data will be reset to whatever the defaults are unless you find a way to store it across scenes (saving to a file would be one way).

Thanks again for clearing that up and the links of course, I learned a lot! :)

I think saving to a file is a little bit excessive though I'm used to having a Main.tscn where everything is loaded in and free'd from when necessary. That's what I meant with basically the same, only that I create the node manually, instead of adding it to the autoloads list and it's also on a different position within the tree.

The advantage in GDScript is; If I would add a GDScript to the autoload list and name it _Data, I could access it by just typing _Data.member. No get_node() needed. Not that much of an advantage, but still pretty neat! But you've pointed out the actual advantage of autoloads by them being outside the scene tree. It didn't occur to me because of how I structure projects.

5 years later