godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.51k stars 21.07k forks source link

[3.x] GDScript autocompletion errors with "Node not found" when using `get_node` with an absolute `/root` path #37371

Open MrRevington opened 4 years ago

MrRevington commented 4 years ago

OS: Microsoft Windows [Version 10.0.18363.720] 64bit Godot: v3.2.1.stable.mono.official 64bit

It seems get_node (same with $) is not working as expected.

Specify steps to reproduce: Suppose you have the following tree: /root/Character /root/Character/Sword

And a script attached to Sword.

Inside that script you have: func _ready() -> void: var bug = get_node("/root/Character")

If you now type bug. below var bug you get "Node not found: /root/Character." in the output window of the editor. Get_node_bug.zip

And you don't get code completion for properties like position if the Character is a Node for example.

KoBeWi commented 4 years ago

Root is the main Viewport node, you are probably confusing it with main scene, which a sub-node of viewport (check Remote Tree to see how it looks in game).

rsubtil commented 4 years ago

What you probably want to do is this:

var bug = $".." # <--- now "bug" is the parent node, aka Character

You should read more of Godot's tutorials to understand the node structure, like this one

Calinou commented 4 years ago

Indeed, it's better to use relative paths in your particular case. If you're unsure about a node's full path, you can always check the remote inspector by running the project, alt-tabbing to the editor and clicking the Remote sub-tab in the Scene tree dock.

Closing, as this isn't a bug.

MrRevington commented 4 years ago

What you probably want to do is this: No i do not want to do this.

var bug = $".." # <--- now "bug" is the parent node, aka Character

You should read more of Godot's tutorials to understand the node structure, like this one

My example is from the offical docs: https://docs.godotengine.org/en/3.2/classes/class_node.html#class-node-method-get-node

Indeed, it's better to use relative paths in your particular case. If you're unsure about a node's full path, you can always check the remote inspector by running the project, alt-tabbing to the editor and clicking the Remote sub-tab in the Scene tree dock.

Closing, as this isn't a bug.

Please see this image: get_node_bug

/root/Character is a valid path

The path works at runtime but the code completion does not and spams the output panel with the "node not found" message.

Root is the main Viewport node, you are probably confusing it with main scene, which a sub-node of viewport (check Remote Tree to see how it looks in game). I don't know what you mean, please see: https://docs.godotengine.org/en/3.2/getting_started/step_by_step/scene_tree.html#root-viewport

But if what you say is correct, should /Character not work? get_node_bug2

It does not and the correct path for my example imho is /root/Character

Absolute node path are supposed to be supported (and do work at runtime) but the editor somehow can't find them for code completion.

If the manual is out of date and it is not supported anymore - it should proably not work at runtime no?

Zireael07 commented 4 years ago

Looks like your path is indeed correct - absolute paths are supported in general but it seems code completion doesn't work with them.

rsubtil commented 4 years ago

/root/Character is a valid path

The path works at runtime but the code completion does not and spams the output panel with the "node not found" message.

It's valid in this specific case. Imagine if you, instead, load this node somewhere else, and run the same code. If the structure is something like /root/World/Town/Character/Sword, your code will no longer work.

It works at runtime, but in the context of the editor, the editor has no clue how does the scene tree look like.

Absolute node path are supposed to be supported (and do work at runtime) but the editor somehow can't find them for code completion.

Yes: you can use absolute node paths. But to reiterate, it's generally a bad idea. It's best to keep your scenes loosely-coupled; otherwise a simple and small change can break your entire project, if you rely on this method.

To quote the page I linked for the wiki, which explains this best:

When Godot users begin crafting their own scenes, they often run into the following problem:

They create their first scene and fill it with content before the creeping sense that they need to split it up into re-usable pieces haunts them. They save branches of their scene into their own scene. However, they then notice that the hard references they were able to rely on before are no longer possible. Re-using the scene in multiple places creates issues because the node paths do not find their targets. Signal connections established in the editor break.

MrRevington commented 4 years ago

It's valid in this specific case. Imagine if you, instead, load this node somewhere else, and run the same code. If the structure is something like /root/World/Town/Character/Sword, your code will no longer work.

Yeah it's not optimal to use nodes like that but there are specials cases were it is fine and also it's not about what is better or worse.

It works at runtime, but in the context of the editor, the editor has no clue how does the scene tree look like.

Well it does have in this case because otherwise none of the get_node variations would work I think or maybe code completion just doesn't support absolute paths.

It's just the error message that freaks me out. 🤣

rsubtil commented 4 years ago

If you were to print the current node structure of the editor, it looks something like this:

/root
/root/EditorNode
/root/EditorNode/@@582
/root/EditorNode/@@584
/root/EditorNode/@@584/@@583
/root/EditorNode/@@585
/root/EditorNode/@@585/@@586
/root/EditorNode/@@585/@@586/@@594
/root/EditorNode/@@585/@@586/@@594/@@595
/root/EditorNode/@@585/@@586/@@594/@@595/@@634
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637/@@636
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637/@@636/@@635
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637/@@636/Export
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637/@@636/Export/@@2768
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637/@@636/RecentScenes
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@637/@@636/RecentScenes/@@2769
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@2772
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@2772/@@2771
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@2772/@@2771/@@2770
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@2772/@@2771/Version Control
/root/EditorNode/@@585/@@586/@@594/@@595/@@634/@@2772/@@2771/Version Control/@@2773
...

This is because the Godot Editor is actually a Godot project.

And this is why the editor gives an error: it can't find /root/Character, or /root/Character/Sword in the scene tree. It's because they only exist on your game: in runtime, not in the editor context.

I think you're assuming that in the path /root/Character, root means the root node of your scene. But in Godot, if you write /root, you're acessing the root node of the entire engine, and not your scene.

If you really need to access the root of your scene from your children's script, you need to find another way. The easiest would be to use relative paths ($"../../..") and backtrack the number of times you need.

MrRevington commented 4 years ago

If the code completetion searches the editor's scene tree for code completion than it is a bug imho because it is not supposed to search the edited scene tree as edited script is not a tool script / EditorPlugin.

KoBeWi commented 4 years ago

Code completion doesn't search editor scene tree. It uses the current open scene. For absolute paths, only root and singleton autocompletion works.

MrRevington commented 4 years ago

Code completion doesn't search editor scene tree. It uses the current open scene. For absolute paths, only root and singleton autocompletion works.

Ok, thanks for the clarification!

Shouldn't there be a warning in the editor that autocompletion is not supported for nodes that are not root or an autoload instead of the "node not found" message? Naive people like me may think there is a typo in the nodepath if you type something like /root/Character and get this error message even tough it is a correct node path.

KoBeWi commented 4 years ago

Ok, it's not clear from your original description, but now I see that there might be some room for improvement here.

To clarify, when you you press Ctrl + Space in this situation image

You get these errors image

The error makes sense, but if user expects it to work in editor, maybe the error could clarify that absolute paths won't work here. Although I haven't seen anyone else with this problem...

@Calinou Is this worth reopening?

Calinou commented 4 years ago

@KoBeWi Indeed, I suppose this is a documentation issue then.

GeorgeS2019 commented 2 years ago

The error makes sense, but if user expects it to work in editor, maybe the error could clarify that absolute paths won't work here. Although I haven't seen anyone else with this problem...

I am attempting to access singleton e.g. /root/Global using Autoload with name Global. This work find in running scene, but not in editor use case as stated above.

Any suggestion how to work around to get absolute path e.g. GetNode("/root/Global") to work in Editor use case?

akien-mga commented 2 years ago

For the record, the reproduction project now triggers this error, which is more explicit and confirms what has been described above:

ERROR: (Node not found: "/root/Character" (absolute path attempted from "/root/EditorNode/@@592/@@593/@@601/@@603/@@607/@@611/@@612/@@613/@@629/@@630/@@639/@@640/@@6275/@@6109/@@6110/@@6111/@@6112/@@6113/Character/Sword").)
   at: get_node (scene/main/node.cpp:1322)

The problem is not that absolute paths don't work with get_node, but that auto-completion happens in the editor and thus the scene tree is not what the user expects. The best solution here would be to disable auto-completion when using absolute paths. The code would still work fine at runtime when the scene tree matches what the user expects from the remote scene tree.

I am attempting to access singleton e.g. /root/Global using Autoload with name Global.

You can't access AutoLoads from the editor, as they are added at runtime. But AutoLoads are made available to your script through their global identifier. See https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html#autoload

akien-mga commented 2 years ago

The issue seems fixed in master: image

It works as I would expect it, i.e. there's no contextual auto-completion of the API of this specific Node2D. It just falls back to offering Node API since that's the common denominator for get_node return.

In 3.x, I see that modules/gdscript/gdscript_editor.cpp has some code to handle /root paths and autoloads specifically. Maybe this can actually be made to work and just needs unification in the various parts that try to handle this gracefully. Or outright disabling as suggested before.