godotengine / godot

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

ViewportTexture: Path to node is invalid #27790

Open fivemoreminix opened 5 years ago

fivemoreminix commented 5 years ago

Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.


Godot version: v3.1.stable.mono.official

OS/device including version: Windows 10.0.17763 Build 17763

Issue description:

I created a Viewport node and had it draw some GUI. Then, on a MeshInstance (quad) I set its albedo texture to ViewportTexture and selected the viewport node (at Player/Viewport). It still came up with a preview.

When I ran the game I was met with two errors:

Node not found: Player/Viewport
ViewportTexture: Path to node is invalid

But I was still able to play the game and furthermore, the viewport still worked correctly. I took a look at the scene's .tscn file and found that the ViewportTexture does indeed point correctly to the Viewport node I had created.

ViewportTexture, SpatialMaterial, and QuadMesh:

...

[sub_resource type="ViewportTexture" id=1]
flags = 1
viewport_path = NodePath("Player/Viewport")

[sub_resource type="SpatialMaterial" id=2]
resource_local_to_scene = true
flags_transparent = true
flags_unshaded = true
flags_albedo_tex_force_srgb = true
albedo_texture = SubResource( 1 )

[sub_resource type="QuadMesh" id=3]
resource_local_to_scene = true
material = SubResource( 2 )
size = Vector2( 0.3, 0.2 )

...

Scene tree:

 ┖╴Spatial
    ┠╴Player
    ┃  ┠╴Camera
    ┃  ┠╴Cockpit
    ┃  ┠╴Right
    ┃  ┠╴Left
    ┃  ┠╴CockpitAudio
    ┃  ┠╴GunFireCockpitAudio
    ┃  ┠╴TargetingMesh
    ┃  ┖╴Viewport
    ┃     ┖╴GUI
    ┃        ┖╴Speed
    ┠╴CSGBox
    ┖╴CSGBox2

This is very similar to #14790, #12781, and #19259. Steps to reproduce: Create a Viewport node, assign a ViewportTexture to a mesh, select the Viewport you made, and run the game.

fivemoreminix commented 5 years ago

Oh, my bad: the error occurs on save, too.

CptPotato commented 5 years ago

I'm having the same issue without using mono. The ViewportTexture is used in a TextureRect and works correctly, but an error message is thrown.

Overblob commented 5 years ago

@asmoaesl @CptPotato, do you use the "tool" keyword in a script attached somewhere in the node hierarchy that includes the Viewport Node?

CptPotato commented 5 years ago

I don't. I'll see if I can create a small reproduction project later today.

kaadmy commented 5 years ago

Can confirm this is happening for me as well with 3.1 stable. A possibility is that for the first frame, the Viewport is invalid/initialized, since this only seems to happen when starting the game or the editor.

fivemoreminix commented 5 years ago

I do not.

On Mon, Apr 8, 2019 at 3:10 PM KaadmY notifications@github.com wrote:

Can confirm this is happening for me as well with 3.1 stable. A possibility is that for the first frame, the Viewport is invalid/initialized, since this only seems to happen when starting the game or the editor.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/27790#issuecomment-480987869, or mute the thread https://github.com/notifications/unsubscribe-auth/ANCVy-PQBnmj1e0YLMannkPKNl-0YrXCks5ve6IpgaJpZM4chGqk .

CptPotato commented 5 years ago

Looks like @kaadmy is correct.

This works without errors: grafik The TectureRect is using the Viewport as ViewportTexture.

This causes an error on the first frame (probably while the tree is being created): grafik

fivemoreminix commented 5 years ago

Good temporary solution

szamq commented 5 years ago

Can confirm the bug

Overblob commented 5 years ago

The workaround is working...but it may break a little the consistency of the node tree, ie: if my Viewport Node is generating a texture specificaly for a Sprite Node, I'm assume it's more logical to have it under the Sprite Node and not before. Thus manipulating the Viewport Node is more straightforward through a script attached to my Sprite Node. Is there any way to skip the first frame otherwise?

CptPotato commented 5 years ago

@Overblob I actually think it makes more sense to have the Viewport above the Node which is accessing it. Not only does it prevent the error, but it also doesn't introduce lag. Otherwise you'll get 1 frame of lag for each consecutive Viewport you're using.

Overblob commented 5 years ago

@CptPotato Makes sense, I didn't think of it. But it still feels weird to have the 2 Nodes at the same hierarchy level since the former is a dependency of the later one (ie. if my Viewport Node is only meant to generate a texture for the other Node). And generally speaking, from a given Node I think it's good practice not to reference a non child Node. Maybe an exception is inevitable in this particular case.

Toshiwoz commented 5 years ago

I have a very similar issue, but in my case I'm using a label under a viewport, and then rendered into a sprite3d that have a ViewportTexture, no matter the order of the nodes, I still get the same error. I have to correct myself, changing order works also with Sprite3D, I just forgot to change reference to if from a script. I'm using Godot 3.1.1

DleanJeans commented 5 years ago

Welp! How you work around this?

image

EDIT: Instead of setting the texture directly from the Inspector, set it from script:

func _ready():
    texture = $Viewport.get_texture()
creikey commented 4 years ago

This seems to be just an issue with the way the _ready notification is passed, the connection is happening before the viewport node is instanced in the tree. Maybe in the other notification that is called after _ready? ( I am forgetting its name right now and cannot find it in the docs )

rcorre commented 4 years ago

This is listed as "similar" to #19259, but are they actually exact dupes?

rcorre commented 4 years ago

I was going to file a separate issue, but I think it is close enough to this to post here. I've got a repro of this even with the ViewPort ordered before the texture, and it seems to be blocking parts of the editor UI.

Godot version:

3.1.2.stable.custom_build

OS/device including version:

Linux 5.4.10-arch1-1

Issue description: 1579042016

When I use a ViewportTexture referencing a ViewPort (A), clicking the arrow on an exported PackedScene field (B) of a custom resource (C) prints the error "ViewportTexture: Path to node is invalid" (D), and no dropdown is shown.

Steps to reproduce:

  1. Open the attached project
  2. Type data in the filesystem searchbar
  3. Double-click bolt/data.tres
  4. Click the arrow on the projectile field
  5. No dropdown appears, errors are printed.

Minimal reproduction project:

Not completely minimal, but I tried to reduce my current project down as much as feasible. example.zip

rcorre commented 4 years ago

Digging further, the issue in mine seems to be that loadout.gd preload's a scene that has a ViewPort texture. If I remove the preload, my errors go away. Haven't been able to minimize it though.

Phischermen commented 4 years ago

An easy solution would be to modify the error that gets printed, to suggest modifying the hierarchy to silence the error. i.e.

"ViewportTexture: Path to viewport is invalid or the texture was instantiated before the viewport. If the path seems valid, move the node using the texture underneath the viewport"

Phischermen commented 4 years ago

I did my own digging and here's what I found:

//path is the viewport path
//path is initialized as an empty path
void ViewportTexture::set_viewport_path_in_scene(const NodePath &p_path) {
    if (path == p_path)
        return;

    path = p_path;

    if (get_local_scene()) {
        setup_local_to_scene(); //This line refreshes texture when path is changed
    }
}

Our issue is that when our scene gets instantiated, path is set to whatever it is in the scene/resource file. This calls set_viewport_path_in_scene() which calls setup_local_to_scene() and since the node is most likely not done initializing, there's potential for a path to be invalid. set_viewport_path_in_scene() is called a second time, after initialization (I don't know from where) so the path will be valid.

I guess the two options would be to change the error message with #37014 or we could somehow check if the node returned from get_local_scene() is fully initialized. But I don't know if such a function exists.

jitspoe commented 3 years ago

I've had this same issue, and I modified the engine to remove ViewportTexture::setup_local_to_scene() and moved the logic to ViewportTexture::set_viewport_path_in_scene(). Seems setup_local_to_scene() is called too soon (before the scene is put into the tree). I'm not sure if there's a reason setup_local_to_scene() needs to be there, but for the two instances I'm using it (reflection on water and rendering something to a monitor), it seems to work properly.

Phischermen commented 3 years ago

@jitspoe Do you think you could share what ViewportTexture::set_viewport_path_in_scene() looks like after you add the functionality from ViewportTexture::setup_local_to_scene()?

jitspoe commented 3 years ago

Pretty much just a copy/paste, I think. I'm a bit hesitant to do a pull request, as I don't know why setup_local_to_scene() was used and what removing it would break.

void ViewportTexture::set_viewport_path_in_scene(const NodePath &p_path) {

    if (path == p_path)
        return;

    path = p_path;

    if (get_local_scene()) {
        if (vp) {
            vp->viewport_textures.erase(this);
        }

        vp = NULL;

        Node *local_scene = get_local_scene();
        if (!local_scene) {
            return;
        }

        Node *vpn = local_scene->get_node(path);
        ERR_FAIL_COND_MSG(!vpn, "ViewportTexture: Path to node is invalid.");

        vp = Object::cast_to<Viewport>(vpn);

        ERR_FAIL_COND_MSG(!vp, "ViewportTexture: Path to node does not point to a viewport.");

        vp->viewport_textures.insert(this);

        VS::get_singleton()->texture_set_proxy(proxy, vp->texture_rid);

        vp->texture_flags = flags;
        VS::get_singleton()->texture_set_flags(vp->texture_rid, flags);
    }
}

Edit: Could stand to be cleaned up. The local scene check is redundant. I just copy/pasted it to see if it would fix the bug.

Calinou commented 3 years ago

@jitspoe Feel free to open a pull request so it can get broader testing :slightly_smiling_face:

markdibarry commented 3 years ago

Using mono here. I also get the same error spam 6-7 times every time the scene loads regardless of the order, and even when programmatically set. Happens all at once, right after the scene's _Ready() method is called, after I lose control of the loop's cycle, and before the next cycle starts.

markdibarry commented 3 years ago

And, like clockwork, after a few weeks debugging this issue, as soon as I post about it, I discover the root of the issue. So, I was avoiding building a minimum reproduction, because it's not simple to replicate, but I took the time and made one, but I couldn't get it to throw the slew of errors. After doing a general string search the entire project for references to the node's name, I found that sometimes (I can't find a pattern) when you pass a ViewportTexture as a parameter to a shader, it will sometimes hold on to the reference to the node in the tscn file even after you clear it. In my case, since I decided to programmatically set the ViewportTexture, it doesn't need to be referenced in the scene, but it persisted in file though it was cleared, and I had to manually remove it from the tscn code. So, while the errors are annoying, they were valid, but only due to another unrelated editor bug. I'll open a separate issue once I've been able to consistently replicate the problem.

jitspoe commented 3 years ago

Did you, by chance, happen to have that as a child scene and have editable children enabled?

markdibarry commented 3 years ago

I'm guessing there's an open bug involved with that? Because totally. I couldn't find documentation on this, but it seems like the little circular arrow next to a setting resets it to whatever the base scene's setting value is. If that is the case, it sometimes shows it update in the editor, but doesn't save it in the tscn.

jitspoe commented 3 years ago

Don't know if there's an open bug on it, but it's something I've noticed with other things. For example, I had a scene that had editable children enabled, then I updated a material on the child scene, but that material didn't update on the scene containing it (even though that material wasn't edited -- I just wanted to move some meshes around or something).

Calinou commented 3 years ago

See https://github.com/godotengine/godot/issues/44024#issuecomment-736905940 for a trace when this error message is printed.

Host32 commented 3 years ago

Same error here, i solved doing what @DleanJeans said:

func _ready():
    texture = $Viewport.get_texture()
jitspoe commented 3 years ago

@jitspoe Feel free to open a pull request so it can get broader testing 🙂

I tried to get mainline up and running, but sadly I just get a black screen at the moment, so I'll have to wait until thing stabilize a bit more. Not sure if it's worth attempting to make a pull request directly into the 3.x branch.

Calinou commented 3 years ago

Not sure if it's worth attempting to make a pull request directly into the 3.x branch.

3.2.x will remain the latest stable version for a while, so I think it's worth the effort.

RicardRC commented 3 years ago

Is there a mirror of this issue for master? Because I'm having similar problems with viewport as the ones comented here, with the difference that reordering does not help and it hangs the running game.

Calinou commented 3 years ago

Is there a mirror of this issue for master? Because I'm having similar problems with viewport as the ones comented here, with the difference that reordering does not help and it hangs the running game.

In my experience, SubViewports are generally broken in the master branch. I'd open a separate issue for it.

jitspoe commented 3 years ago

Bad news: I've figured out why the setup_local_to_scene() is necessary. It's needed for things to display properly in editor. Without my change, the text in the viewport shows up in-editor the same as in the running game. With my change, it does not: image

Not sure of a good way to fix this without re-introducing the error.

jitspoe commented 3 years ago

I think I may have a solution here: https://github.com/godotengine/godot/pull/52365

Would be great if some of you who have errors could test it!

coelhucas commented 2 years ago

Just a heads-up that I am still able to replicate this using a Viewport as a texture for a Sprite3D on 3.4.2 (not sure if #52365 really made it to 3.4). I had to use this as a workaround for now.

YeldhamDev commented 2 years ago

Indeed, I can replicate the issue on both 3.5 and master.

textrivers commented 1 year ago

In v4.0 beta 2, I'm getting the error "ViewportTexture: path to node is invalid" whether or not the target subviewport is below. So to be clear, the workaround above is not working for me. In case it's relevant, the project was started in 3.5 and migrated to 4.0.

croxis commented 1 year ago

I am also getting this error in 4.0.1. In the editor the node acts if it forgets what the texture is when the scene first loads. If I clear and recreate the material the viewporttexture works for a while.

isaaccp commented 1 year ago

Update: Nevermind, my issue below was: https://github.com/godotengine/godot/issues/60350#issuecomment-1445114437 I am not sure if this is the same issue or a separated (although related one).

I was getting the warning mentioned in the bug (ViewportTexture: Path to node is invalid), but my game worked fine when running it from the editor.

I have now exported it to a Windows executable and my ViewportTextures don't seem to work at all (getting same warnings).

PixelDrennen commented 11 months ago

You can see the issue I was having in #83350 -- The problem is in godot 4.2 mono. I am instantiating the scene that has my subviewport from code. If there was some way to hush the error it would be fine for me because I don't think it's causing issues, but also would be nice to fix the root of the issue.