godot: ViewportTexture: Path to node is invalid


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.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 38
  • Comments: 43 (34 by maintainers)

Commits related to this issue

Most upvoted comments

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

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()

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.

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.

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”

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.

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.

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.

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.

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.

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

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.

@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.

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).

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

@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()?