How to build a 2D Open World?

Godot Version

4.4

Question

Open world is a bit too much. But basically, I want to connect (visually) 2 scenes into 1 bigger scenes so the player can move from 1 scene to another without loading/changing scenes. For instance, I have scene jungle J and scene river R. Normally if player P move from J to R I’ll have to load R scene and display it (a jump between scene with/without animation). But I want to do this:

  1. preload scene R when P are in scene J
  2. and the draw scene R once camera of P moves into the edge zone of scene P (scene J is still there at this step)
  3. then destroy scene J once camera of P completely moves out of it.

This steps will keep repeating for all the scenes in game.

Do you think Godot can do this? If so what kind of nodes and functions for it? Thanks in advance.

VisibleOnScreenNotifier2D and its close buddy VisibleOnScreenEnabler2D seem like good choices here.

1 Like

I don’t know how exactly your game works, but i would not unload J as soon as R takes up the whole screen.
What would happen if your player moved back? Now you have a not loaded J that wants to be displayed.

Try loading your current scene and all scenes your player can directly travel to, forward or backwards and if you have more (up, down, hidden door, etc.), those as well. As long as there are not too many and too big, this should work just fine.

You can then unload the ones that are 2 or more scenes away, so when coming from R in, say, G (grass), you can unload J because someone would need to travel through R to get there.
This makes sure the will always be the sceanes loaded you need to display.

1 Like

You ought to be able to do something like this; I’m assuming you plan to have a combination of scenes that’s bigger than you’re comfortable having all loaded at once.

A potential solution is to make a streaming level chunk manager. It could be some node in the scene tree whose job is to keep the current chunk and any visible or adjacent chunks loaded.

If a new chunk will become visible soon, the manager would load it, instantiate it, set its position appropriately, and add it to the tree. If a chunk is no longer needed, the manager can queue_free() that chunk.

The question of what chunks are needed (as @Darnok points out) depends on your level layout. Is your world strictly linear, with no backtracking? Linear but the player can go anywhere they like within it? A 2D map the player can wander as they please?

In every case, though, once the decision is made, whether it’s “we need this chunk because that’s where the player is going” or “we need this chunk because if the player heads straight for it we only barely have time to load it”, presumably you have a priority sorted list of chunks to load, and the mechanics of loading the chunks is the same.

The main challenge is going to be making sure things load in time. Worst case, depending on the platform, some of your players may be playing your game off of a low speed hard disk that the OS has decided to defrag, connected over USB 1.2.

The classical fix for this is to have some mechanism that stalls the player that makes sense in-game. Maybe an airlock slams closed and there’s a hull breach alarm until the load completes. Maybe the area gets blocked off and there’s a “random” fight that keeps the player there until the chunk is loaded. Maybe a wizard teleports the player back a screen, or a strong wind impedes their progress.

Whatever you do, you want to think about some way that makes sense in-game to keep places out of view until they’re properly loaded, even on slow garbage potato machines. Hopefully you can load enough chunks that it’s rarely needed, but unless you can fit the whole game in memory all at once, it’s almost inevitably going to be needed.

1 Like