Topic was automatically imported from the old Question2Answer platform.
Asked By
pillus
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:
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?
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.
Yes, use an autoload. Here’s official documentation:
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