I have just made a Scene whiches sole purpose it is to store Keyboard Shortcuts such as ,,F11 for Fullscreen", which should be accessible throughout the entire game, without any exceptions.

Is there a way to keep this scene persistent as soon as it's loaded from my Intro scene, without having to drag it into every single other scene?

You can add an autoload script that adds the scene as its child, which effectively would keep the scene in memory for the entire duration of the game. It is probably not the best solution, but it should work in a pinch.

@TwistedTwigleg said: You can add an autoload script that adds the scene as its child, which effectively would keep the scene in memory for the entire duration of the game. It is probably not the best solution, but it should work in a pinch.

I'm looking for a long-term solution.

@Sosasees said:

@TwistedTwigleg said: You can add an autoload script that adds the scene as its child, which effectively would keep the scene in memory for the entire duration of the game. It is probably not the best solution, but it should work in a pinch.

I'm looking for a long-term solution.

In that case, I would probably still suggest using an autoload script, but I would add some helper functionality to avoid some potential pitfalls that could come back to bite you later.

The first thing I'd recommend for a long-term solution is making sure there is a condition to make sure the autoload you are wanting to add does not already exist, as this could be a issue later that would be hard to debug. It likely won't crop up, but if it does, you'll save yourself some trouble down the road I would also add a function so you can get a reference to the scene from the function, so if you need to change things later, it should be easier since there are no hard-coded paths. Thankfully, all of this should be fairly easy to do. Here's how I would approach it:

extends Node
const AUTOLOAD_ID = "insert_a_unique_id_here"
const desired_scene_file = preload("res://path_to_scene.tscn")
var desired_scene = null

func _ready():
	# make sure the autoload does not already exist
	# I think the follow code should do it, but it's been awhile since I've worked with autoloads.
	for root_child in get_tree().root.get_children():
		if "AUTOLOAD_ID" in root_child:
			if root_child.AUTOLOAD_ID == AUTOLOAD_ID:
				queue_free()
				return
	
	# add the scene to the autoload.
	desired_scene = desired_scene_file.instance()
	add_child(desired_scene)

func get_desired_scene():
	if desired_scene == null:
		print ("WARNING: Autoload does not have the desired scene! Returning null...")
	return desired_scene

Then when you are using it, you can do something like the following:

# We'll assume the autoload has been named "autoload_node" in the project settings
var desired_scene = autoload_node.get_desired_scene()
if desired_scene != null:
	desired_scene.do_something()

That said, there may be better/easier ways to handle this, but that is probably how I would go about it, if this were my project. The only issue with this method is that garbage collection will not clean up the scene (which is probably not an issue since you need it everywhere), and any executions running on these nodes will not be interrupted when changing scenes. To fix the execution issue, you can add a function to change scenes to the autoload that handles stopping the scene:

func custom_load_scene(scene_path):

	# two ways to do this. Either have a function that will stop the execution
	# or delete the node and then add it after loading.
	# You can also use both, if you want (that's what I've done here)
	
	if desired_scene != null:
		if desired_scene.has_method("_on_scene_change":
			# call a function that can be implemented to stop execution of processes!
			desired_scene._on_scene_change()

	# delete the node
	if desired_scene != null:
		desired_scene.queue_free()
		desired_scene = null

	get_tree().change_scene(scene_path)
	
	# add the node back!
	if desired_scene == null:
		desired_scene = desired_scene_file.instance()
		add_child(desired_scene)

For the purposes of toggling fullscreen, you can do so directly in an AutoLoad. It doesn't matter where the AutoLoad is in the scene tree for this to work. It's as long-term as it can be :)

Now I know why many games have a splash screen with company logos: It actually serves TWO purposes:

  1. The Splash Screen is not only the ideal opportunity to load the game, but also to load Autoload scripts. Since you can't return to the Splash Screen at any point in the game, unless you exit and later restart the game, it ensures that the Autoload scripts are never accidentally loaded twice.
  2. Showing a slideshow of the Company Logos during the process makes sure that the players know which companies worked on the game. This is much better than just making the screen black, since a black screen is static, which creates ambiguity if the game is actually loading or if it froze.

I'll definitely add a Splash Screen Scene to my game, for Reason #1 from above. To make it seamless, I'll make my Splash Screen Scene look identical to the Splash Screen I'll set in my Project Settings. This Splash Screen Scene will contain a Node which will then travel through ALL the scenes the player visits in the game, making the Node persiestent.

ADDED PARAGRAPH: I overthought the previous paragraph. I just found the ,,Autoload" tab in the Project Settings. Godot is the best game engine for exactly these kinds of things: It makes everything easier while also being complicated enough to be a fully-featured FOSS game engine.

@Calinou Thanks very much for the Simple answer. I couldn't comprehend @TwistedTwigleg 's answer, but you made it clear that all this extra stuff in their answer is not needed if the Autoload Script only contains Keyboard Shortcuts, which is the case for my game. I'll credit you in my Game Credits if you don't disagree by tomorrow 12:00 pm

Many games also use the splash/loading screen as an opportunity to compile shaders.

2 years later