godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add level streaming and stitching tools for creating large open worlds #1197

Open jonbonazza opened 4 years ago

jonbonazza commented 4 years ago

Describe the project you are working on: Online multiplayer games with large open worlds

Describe the problem or limitation you are having in your project: We build online multiplayer games and some of these games use large open worlds. Large open worlds are not unique to online games however. Creating large worlds, regardless of whether they are online or offline, pose a lot of challenging problems, not only from the game's perspective, but also from the content creation/editing perspective. A lot of the solutions to these problems are fairly game specific and thus, easier to address as either published add-ons or project one-offs. Two of the biggest problems are better solved by core engine however, as they are fundamental ton working with large open worlds:

  1. Level/Asset streaming
  2. Level creation/stitching

Describe the feature / enhancement and how it helps to overcome the problem or limitation:

Level/Asset streaming

Level streaming is where the content of a "level" is streamed from disk as needed, rather than all of the level loaded into memory at once. Since large open worlds contain so much data, it's generally impossible to fit all of the necessary data in a reasonable amount of memory.

This problem can be solved in a couple different ways. The first approach is Geometric Volumes. This approach is simple, but it can be extremely cumbersome to use and as such, is not really considered ideal. The way it works is that the developer creates their level in the editor and then manually places a number of bounding volumes around certain parts of the level, with some overlap. When a player enters one of these volumes, everything within the volume is loaded and when a player leaves one of these volumes, everything within the volume is unloaded. There are a couple major problems with this approach however. First, the nature of the solution does not lend itself well to development. Not only does it require the manual placement of volumes (an extremely tedious task) it requires that the entire level be loaded in the editor, which means that in order to create these kinds of games, an extremely powerful computer is necessary.

The second solution to this problem is basically an extension of the first solution. It comes from realizing that the creation of volumes is a very automatable process. By automating the creation of these volumes by simply generating an infinite grid, you remove the step of having to manually place the volumes, which is great, but you also gain the benefit of being able to create this same grid in the editor, meaning that the editor camera can be used instead of the player in order to handle level streaming during development. This way, not only do you gain the benefits of level streaming while the game is running, but you also gain the same benefits in the editor while developing the game.

This is the solution most commonly used. As a bonus, this solution also lends itself well to online multiplayer games, where you only need to replicate objects that are within a certain "area of interest" but that's a discussion for another time.

Level Creation/Stitching

This problem is more of a problem for developers in that, supposing that the above solution to level streaming is adopted, a good editor experience is necessary for both creating levels, as well as easily stitching existing "sections" of a level (possibly created outside of the engine in a DCC) together to create the overall world. Part of a possible solution to this is elaborated on above.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

I did this in the above section as it was easier to answer both of these at once.

If this enhancement will not be used often, can it be worked around with a few lines of script?: Technically speaking, these two fundamental components can be implemented as EditorPlugins using things like Area2D /Area nodes, but I worry about the performance of such an approach, not only from the performance characteristics of GDScript, but also the fact that Area(2D) nodes aren't designed for such a use case and their performance might not be up to the challenge. Something more tailored would be more ideal.

Is there a reason why this should be core and not an add-on in the asset library?:

I agree that anything beyond these fundamental building blocks makes better sense as game specific tools (possibly publihsed as a 3rd party addon in the asset lib), however these two things are so ubiquitous for large, open world games, that other engines are also taking a similar approach. As one example, see the upcoming large open world features in the Unreal Engine.

I should also note that, at least for 3D, this feature doesn't make much sense until 4.0 when the rendering pipeline has been overhauled. The performance of 3D in godot simply isn't sufficient to run a large open world game, even with such optimizations such as level streaming, in any by the lowest-poly of games.

Jummit commented 4 years ago

Note that if the only thing stopping it from being a plugin is performance, there is still the possibility of using GDNative. I don't know if this should be in core, but I'm interested to see other peoples opinions.

jonbonazza commented 4 years ago

It could likely be a gdnative plugin as long as EditorPlugins can be coded in gdnative (assuming they can be). The other big thing besides performance is the implementation of the infinite world grid. Not sure how feasible that would be to add to a game and editor as a plugin. Im certainly open to that if it comes to it and it's feasible, however maintaining gdnative plugins for all platforms is difficult and i think with the graphical improvements coming in 4.0, open world games will be far more common in the future, so having at least the fundamental components in core would be nice, imo.

jonbonazza commented 4 years ago

Also, can gdnative plugins be published to the assetlib?

Jummit commented 4 years ago

Also, can gdnative plugins be published to the assetlib?

Yes.

Xrayez commented 4 years ago

I guess one of the concrete things which Godot could provide in core is Sparse Texture support: godotengine/godot#17470, or something similar to it.

armzzz commented 3 years ago

Another good reason for having this implemented as a core feature of Godot is the different performance characteristics of various hard drives and SSDs. Since some devices read data slower than others, it becomes a challenge to test and implement an open world level streaming system on one's own, simply because a small developer probably can't afford to acquire and test the wide variety of devices a game can run on. If the level data is being streamed in too slowly, that can cause all sorts of issues for the game.

With a built-in streaming system, Godot can integrate a debugger feature that will let the developer know how much data is being streamed and if that amount of data is too high for low-end devices, which would greatly help in development. Then the developer can adjust assets, reduce chunk sizes, slow down the player, or implement whatever other measures are necessary to ensure the world streams in at a proper rate to not disrupt the game. This is something your average Godot user wouldn't be able to implement on their own, so having it built-in would be a huge benefit for them.

Calinou commented 3 years ago

This is something your average Godot user wouldn't be able to implement on their own, so having it built-in would be a huge benefit for them.

While level streaming will likely have to be done in core for various reasons, nothing prevents an add-on from adding editor tools for easier debugging and profiling :slightly_smiling_face:

NineAlexT commented 3 years ago

I think the simplest way would be to expect users to store sub-levels/streaming levels in separate scene files, improve the ResourceInteractiveLoader to make it more automatic so that the user only has to make one call to it to get it to load a resource, then for the editor provide a right click option on any external scene to load/unload it in editor to maintain performance, and something similar to the "Editable Children" check box except that any changes made that scene would be saved directly into the sub-scene and not as modification of it in the current scene. Perhaps a "make current scene" button that would highlight that sub-scene in some way and lock you from editing other scenes similar to UE4's "Levels" box? I'd assume that's easier said than done though?

Either way this would cover the simple cases of level streaming for linear games or "room" based games like Legacy of Kain: Soul Reaver, The Metroid Primes, or the non-open world Zeldas. Open world tools could be built off those later, as for most open world games you'd want a terrain system, proxy mesh generation tools for HLoDs or similar, a foliage system that generates billboard LoDs and handles batch rendering of trees, and a lot lot more. Also the production of full open world games, unless very limited in scope outside of level size, is beyond what most of Godot's current users could reasonably expect to achieve. if it's not felt to be redundant I can do a bit of research make more detailed and separate proposal/request for the "simple level streaming" use-case.