For performance the best method is definitely collision masking, even though you don't want to go for that option (by the way, you can shift-select multiple nodes to change their properties and layers all at once).
After setting it all in the editor up you only have to set_collision_mask_bit
to false on the player for that layer mask at runtime:

But there is an alternative, easier (to set up) but far less performant method which is to simply delete scenes from the Scene Tree using queue_free()
and then load them back in again later:
Apart from all the conditions driving this particular scene, all the code that matters for instancing is the following:
# Scene 2 (re)loading code.
scene2 = load("res://Scene2.tscn").instance() # (re)load the scene
add_child(sceen2) # 'add as a child' of the main scene
scene1.queue_free() # delete the current scene
# Scene 1 reloading code.
scene1 = load("res://Scene1.tscn").instance()
add_child(sceen1)
scene2.queue_free()
I have uploaded the full demo from this on Github if you want to try it out.
And performance naturally won't be negatively affecting most machines but you may need to implement loading screens on slower devices.
Hope it helps!