Is there a way to restart your game?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By stella3321

So my game has multiple scenes. And its going to be shown at an exhibition for a couple weeks, I obviously wont be present every single time someone plays it so I need the game to restart automatically after its reached its ending.
I have autoload items in the game that are set to disappear once collected so that if the player falls off a platform and that specific scene gets reloaded, they don’t have to recollect the items.
So i cant just use get.tree().change_scene() because then those items wont be reloaded.
and I also cant use get.tree().reload_current_scene because I need the whole game to reload.
Any tips?

:bust_in_silhouette: Reply From: Zylann

Autoloads are indeed a problem when they start containing a lot of per-session global state. It’s one reason I tend to avoid them.

Perhaps you could still reload the scene, but also add a new function to your autoload for cleaning up any dynamically-allocated stuff and resetting all its variables. This way you can get your game to restart without looking too janky.

I was also thinking, since autoloads are just nodes in the tree, you could delete them too and re-create them under the same parent (the scene tree’s root), but I don’t know if that would cause side-effects on their availability as a global variable in GDScript. Maybe worth trying.

A last resort solution (I haven’t tried tho) would be to use OS.create_process (OS — Godot Engine (stable) documentation in English, or create_instance?) to execute the game itself and then quit the current instance with SceneTree.quit, so that it basically restarts the app.

:bust_in_silhouette: Reply From: tuon

If by “autoload items” you mean autoload singletons, I would not use them in the way described.

I use a game state system that would eliminate this issue, but is probably too much to deal with before the exhibition. (The code is here if you are curious. There’s a video along with it too. Link in the readme.)

What I suggest and have done when I want something quick is to use the autoload to denote which collectables have been collected. Give each collectable a key of some sort (the path could work too). When the collectable’s ready function runs, check with the autoload if it’s been collected and call queue_free if it has.

Then at the end of the game (or maybe back on the title scene) clear out the autoload’s collection list.

The same autoload could contain data about what’s in the inventory or current score, etc. Whatever data you want to be kept around for the same game session.

How would i code the clearing of the autoload collection list? like what would the line of code for that look like?

stella3321 | 2023-07-04 18:31

I would code the autoload like this. Let’s say it’s called CollectableMgr.

To answer your question directly: call the CollectableMgr.clear() method coded below right before restarting the game from the beginning.

extends Node

var _collectables := []  # note: if > 100 collectables or so use dictionary instead

# call CollectableMgr.item_collected(get_path()) when item is collected
func item_collected(key: String) -> void:
   if !_collectables.has(key):
       _collectables.append(key)
   else:
       printerr("CollectableMgr: duplicate item key %s" % key)

# call CollectableMgr.is_item_collected(get_path()) - queue_free collectable if returns true
func is_item_collected(key: String) -> bool:
   return _collectables.has(key)

# call CollectableMgr.clear() before restarting game from begining
func clear() -> void:
   _collectables.clear()

This assumes that the path of each collectable node is unique. As long as each level’s scene root node is named differently, this should be true.

If you have > 100 collectables, using a dictionary would be better, but I don’t think the code above changes much except having to store a bogus value when adding the key (e.g. Dictionary[key] = key).

tuon | 2023-07-04 22:58

thank you this worked!

stella3321 | 2023-07-05 13:32

:bust_in_silhouette: Reply From: rakkarage
# Restart the application
func restart_application():
    var executable_path = OS.get_executable_path()
    OS.execute(executable_path, [])  # Pass any command line arguments if needed
    get_tree().quit()  # Quit the current instance of the application

maybe something like this? idk

while this does restart the application, for some reason it doesnt quit the current instance of application, so at some point the computers gonna have a hundred windows open with old applications of the game

stella3321 | 2023-07-05 13:04