godot: ParallaxBackground not showing in secondary viewports

Godot version

v4.1.dev3.official [a67d37f7c]

System information

  • OS: Windows 11
  • Godot version: v4.1.dev3.official [a67d37f7c]
  • Renderer: Vulkan
  • Videocard: GTX1060

Issue description

When adding an extra viewport for a split-screen game and two camera’s the ParallaxBackground TileMap doesn’t show on the second viewport (All other nodes do show). In the player code I use these lines to assign the camera to the right viewport: image

func _ready():
	var viewport = get_node('/root/BugDemo/GridContainer/SubViewportContainer' + str(player) + '/SubViewport')
	var game = get_node('/root/BugDemo/GridContainer/SubViewportContainer1/SubViewport/Game')
	viewport.world_2d = game.get_viewport().world_2d
	$Camera2D.custom_viewport = viewport
	$Camera2D.make_current()

The ParallaxBackground TileMap only shows in the first viewport.

Steps to reproduce

The example project below demonstrates the issue.

Minimal reproduction project

parallaxissue.zip

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 16 (11 by maintainers)

Most upvoted comments

Thanks for taking the time to elaborate on this. I’ll be using a custom solution for parallax scrolling with multiple viewports.

Because it is a CanvasLayer, it’s how it gets the functionality, what is your argument that it should be different?

Which functionality? Inheriting from Node2D doesn’t change any of it’s functionality, it works well.

Then this bug isn’t about ParallaxBackground but about CanvasLayer, and can’t be fixed by changing the former

yes

This is not a solution, just to be clear, ParallaxBackground is supposed to be a CanvasLayer, this isn’t an oversight, this isn’t an issue or an error

Thank you, can you please explain why it inherits from CanvasLayer? It’s the only node that inherits from that class in the engine. If it’s only for z-order the ParallaxBackground could be a child of CanvasLayer in the tree.

These two lines are identical, so nothing changes here, CanvasLayer.get_id() returns an RID

get_viewport().get_id() isn’t available on Node2D.

I think the issue is with CanvasLayer itself. It has a custom_viewport member, that may not work with multiple camera’s and viewports. I’ve replaced the ParallaxBackground with a CanvasLayer in the attached demo project and it also doesn’t show on other viewports.

parallaxissue.zip

I did a little digging and found a possible issue, the ParallaxBackground is inherited from CanvasLayer, and it doesn’t seem to pickup the right viewport. I made a little patch to make it inherit from Node2D instead and now it does show in all viewports, but the position is not correct and the set_layer(…) isn’t available. I’ve also noticed that the canvas layer items have a different camera group name: “__cameras_c” instead of “_cameras” but just changing that didn’t seem to work.

diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index 3d57aaf6aa..a99ba2ce0f 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -35,7 +35,7 @@
 void ParallaxBackground::_notification(int p_what) {
        switch (p_what) {
                case NOTIFICATION_ENTER_TREE: {
-                       group_name = "__cameras_" + itos(get_viewport().get_id());
+                       group_name = "__cameras_" + itos(get_viewport_rid().get_id());
                        add_to_group(group_name);
                } break;

@@ -73,7 +73,7 @@ void ParallaxBackground::_update_scroll() {

        Vector2 scroll_ofs = base_offset + offset * base_scale;

-       Size2 vps = get_viewport_size();
+       Size2 vps = get_viewport_rect().size;

        scroll_ofs = -scroll_ofs;
        if (limit_begin.x < limit_end.x) {
@@ -186,5 +186,5 @@ void ParallaxBackground::_bind_methods() {
 }

 ParallaxBackground::ParallaxBackground() {
-       set_layer(-100); //behind all by default
+       // set_layer(-100); //behind all by default
 }
diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h
index 70766ae7fa..b2ed69a9db 100644
--- a/scene/2d/parallax_background.h
+++ b/scene/2d/parallax_background.h
@@ -31,11 +31,10 @@
 #ifndef PARALLAX_BACKGROUND_H
 #define PARALLAX_BACKGROUND_H

-#include "scene/main/canvas_layer.h"
-
-class ParallaxBackground : public CanvasLayer {
-       GDCLASS(ParallaxBackground, CanvasLayer);
+#include "scene/2d/node_2d.h"

+class ParallaxBackground : public Node2D {
+       GDCLASS(ParallaxBackground, Node2D);
        Point2 offset;
        real_t scale = 1.0;
        Point2 base_offset;