0 votes

I am trying to come up with a nice system to easily add new scene transitions, and make sure that the player is located in the right position when the scene has loaded.

This is how far i have come with a demo:

Think of 2 entrances, which will teleport you to 2 different scenes:
https://imgur.com/a/pz4kb

Currently i tried to create 2x area2d nodes, with a collision area. One named TeleportSource, and one named TeleportDestination.

I create an instance of TeleportSource and add it in front of the entrance. I then create an instance on the new Scene i am going to, and create an instance of TeleportDestination.

Gdscript for Source:

extends Area2D

export (PackedScene) var SceneDestination

func _on_TeleportSource_body_entered( body ):
    print("entered")
    get_tree().change_scene(SceneDestination.resource_path)

Then on Destination i have:

extends Area2D

export (PackedScene) onready var PlayerInstance
export (NodePath) onready var TeleportDestination

func _ready():
    var Player = PlayerInstance.instance()
    add_child(Player)
    Player.position = get_node(TeleportDestination).position
    print ("Teleporter is: ", get_node(TeleportDestination).position)
    print ("Player is at: ", Player.position)

So now i can freely enter the first room, and go back out again without any issues.

The problem exists when i have 2 entrances like on the picture, as there is no way for the engine to know which room i am coming from.

The question is then:
Is my approach totally wrong?
Or should i create a variable on each scene, that is then sent to a singleton, to let my script know where i came from?
Any other approaches?

in Engine by (17 points)

2 Answers

+3 votes
Best answer

Yes, use an autoload. Here's official documentation:
http://docs.godotengine.org/en/latest/getting_started/step_by_step/singletons_autoload.html?highlight=set_current_scene

And here's my code based on official docs that handles passing parameters:

extends Node

var m_sceneParams = null     setget deleted, getParams
var m_currentScene = null    setget deleted


func deleted():
    assert(false)


signal currentSceneChanged()


func _ready():
    var root = get_tree().get_root()
    m_currentScene = root.get_child( root.get_child_count() -1 )


func switchScene(targetScenePath, params = null):
    # The way around this is deferring the load to a later time, when
    # it is ensured that no code from the current scene is running:
    call_deferred("deferredSwitchScene", targetScenePath, params)


func deferredSwitchScene(targetScenePath, params):
    if targetScenePath == null:
        return

    assert( m_sceneParams == null )
    m_sceneParams = params

    # Immediately free the current scene,
    # there is no risk here.
    m_currentScene.free()

    # Load new scene
    var newScene = ResourceLoader.load(targetScenePath)

    # Instance the new scene
    m_currentScene = newScene.instance()

    # Add it to the active scene, as child of root
    get_tree().get_root().add_child(m_currentScene)

    # optional, to make it compatible with the SceneTree.change_scene() API
    get_tree().set_current_scene( m_currentScene )
    emit_signal( "currentSceneChanged" )


func getParams():
    var params = m_sceneParams
    m_sceneParams = null
    return params

Notice that getParams() will nullify parameters after one call. This is done to ensure scenes are getting their parameters.
m_sceneParams can be anything. Use Dictionary if you have no better idea :)

by (2,294 points)
selected by
+1 vote

You need some kind of scene manager, that handles different scenes (which is a scene itself). This is what I do, I put variables in there, that are used globally, in a dictionary like this:

extends Node2D

var game_var = {"last_scene":"bla", "current_scene":bla2, "health":100}

It's basically similar to singleton approach. This way you can access them anywhere and also easily store those needed variables in files, when you need to save your game.

by (840 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.