godotengine / godot

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

GridMap is always visible when in a scene loaded through a script #83632

Open MichaelMacha opened 1 year ago

MichaelMacha commented 1 year ago

Godot version

4.1.2

System information

Linux Mint 20.3

Issue description

I am attempting to set up a system in a platformer in which some blocks can be toggled on and off via a switch. This involves changing their collision layer, and their visibility, based on signals. It works fine when I run the map via F6 (this map only), but the grid maps are always initially visible, regardless of their state in the inspector, when loaded from another scene. (Collision seems to turn off just fine, but not visibility.)

image (Intended)

image (Loaded from script)

The loading script is relatively simple:

extends Node3D

func _input(event):
    if event.is_action("jump"):
#       get_tree().change_scene_to_file("res://scene/World.tscn")
        get_tree().change_scene_to_packed(preload("res://scene/World.tscn"))
#       get_tree().change_scene_to_packed(preload("res://scene/Test.tscn"))

This affects both change_scene_to_file and change_scene_to_preloaded.

I created a test scene to ensure that my issue was not related to my other scripts, and confirmed it there as well. (Test scene and title scene, with relevant script, will be uploaded; texture and sound assets mostly removed for the sake of brevity).

I believe that this is a bug in the engine or editor, as behavior is inconsistent.

Steps to reproduce

Create any two scenes, with one loading the other via get_tree().load_scene_from_*, and add a gridmap to the loaded scene. Toggle its visibility to false. Note that it loads fine with F6, invisible grid map, but loading it from the other scene always has the grid map visible.

This carries over into game builds. Moreover, I've looked at the inpsector on Remote mode and noted that the inspector thinks the grid map is not, in fact, visible, but it is.

image

Minimal reproduction project

bug report gridmap.zip

MichaelMacha commented 1 year ago

As an additional note, if I hide it via hiding its parent, instead of the GridMap directly, it seems to work as expected, including on its child GridMap node. That definitely messes with my architecture... but, it opens up the possibility of a workaround. I'll report back when I'm sure.

Calinou commented 1 year ago

The easiest workaround is likely to use $Path/To/GridMap.set_deferred("visible", false).

MichaelMacha commented 1 year ago

@Calinou That might do it, but having to set it in script consistently is kind of going to get in the way of my level-design workflow. I'm aiming for a toggle box. I did do something very similar, though.

All initial management of being hidden and disabled happens with a script attached to a parent node, rather than the GridMap itself. When hiding, rather than setting visible on the GridMap and changing its collision property, it simply removes the whole node from the tree, after keeping a reference to its original parent; when it's toggled back on, by switch or timer, it simply re-adds itself to the same parent. This allows for other nodes to take advantage of the same system, as children of the vanishing node.

There's a little bit of call_deferred in there to ensure everything works out smoothly, especially with the initial _ready check.