How can I organize many levels in my project? (100+ levels)

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

I need to organize my levels in a such way that I can simply let the player continue to the next level. I already had this function working with a simple exported array, but it was hard for me to edit the order of levels and if I accidentally reset the list it seems I can’t revert it with CTRL-Z.

Basically, I want the same functionality, but I also want it to be easy to edit (and also hard to reset the whole list)

:bust_in_silhouette: Reply From: Zylann

My game has dozens of levels and that problem quickly appeared.

At first I had the name of the next level inside the end portal of each level. That worked, but at some point it became hard to have a big picture, and it forced to open the levels to see that order. Not nice if you want to generate the level map in the main menu.

So I thought I would give them a name with a number at the end, and keep it in a variable. So for example if I play level42.tscn, I know I can extract the 42 using name.to_int() and load level43.tscn by doing str("level", num + 1, ".tscn").
This worked for a while, until I started shuffling the order. Renaming levels wasn’t nice, and I started getting lost in remembering which levels contained what, because they were all numbers, not very descriptive…

So I changed my approach and went for an array, written inside a script file:

# level_list.gd
const _order = [
	# World 1
	"level0_tuto",
	"level0_tuto2",
	"level1",
	"level2",
	"level3",
	# World 2
	...
]

static func get_level(var index: int):
	return load(str("res://levels/", _order[index], ".tscn"))

It is technically the same as a config file, except it’s straight GDScript without the need to parse or anything like that. I can also use a function to make access cleaner. I find it more convenient than editing inside the Godot inspector as well, which is lacking in re-ordering functions etc.

Then I can access it easily anywhere, because it’s just constant data:

# In some script of the game
const LevelList = preload("res://level_list.gd")

func some_function():
    var next_level = LevelList.get_level(current_level + 1)
    ...

Using preload is just a convention of mine. You can make the list available globally using class_name, or using the script into an autoload node.

What would be the best way to current_level? By using get_level and passing the current_scene filename to it to grab the index?

elvisish | 2021-07-29 23:47

:bust_in_silhouette: Reply From: Sween123

Yes this kind of problem like organizing lots of scenes are likely to come when we do a huge world consists of different subscenes or just simply when there are too many levels. Sometimes we may want to change the name of levels or change the orders.
Using a simple array will become quite inconvenient the the number of scenes increases.
So, for each level, or even subscenes of a level where you can go through a portal or something, having some kind of variables like this: lead_to_level and id, and having functions like get_level_by_id(id) or get_id_by_level_name(Name) in a node which I like to call “CONTROL” or a child node “Info Getter” which is actually just a script I use containing important funtions or as a Info Getter.
So for example, you have a scenes FOREST_LEVEL_1, FOREST_LEVEL_2, DESERT_LEVEL_1, you can put id to each of these scenes: 1, 2, 3.
Then, in your functions like get_level_by_id(id) or get_id_by_level_name(Name), you do if statements. (For example, if id == 1: Level = FOREST_LEVEL_1)
After this you can put in the lead_to_level in each of these scenes, it can be an id, or name, depending of which one you like. Then whenever you finish a scene, you can always use one function like go_to_next_level() that will use get_level_by_id(id) or get_id_by_level_name(Name) where lead_to_level will be passed as an arguement.
If you like, actually you can even export var lead_to_level so you can design this in scene editor, which will come in handy for setting up a huge game world contains tons of different interconnected scenes. Using export var like this can also allow you to use one script for all level scenes if you want.
For just one level after another but there are lots of levels, it’s the same. It’s convenient for connecting scenes and levels and organizing them. When you rename a scene, you just update the names in get_level_by_id(id) or get_id_by_level_name(Name).