godotengine / godot-proposals

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

Separating World/World2D and viewport functionalities #2638

Open PaperMartin opened 3 years ago

PaperMartin commented 3 years ago

Describe the project you are working on

A diablo 3 inspired hack & slash

Describe the problem or limitation you are having in your project

Diablo 3 features multiple map instances that can run in parallel (open world maps, dungeons, etc), as in it's entirely possible in a multiplayer session (which would be on one single server) to have peoples running around in different maps that aren't in the same physical world. Currently in godot, spatial nodes add themselves to a world. The problem is, they find this world in their parent viewport. There is no other way afaik to set which world spatial nodes are part of. What this means is that in order for a world to exist and be simulated, they must be part of a viewport, which is a UI element. If I want to have multiple worlds running in parallel, I end up having to juggle multiple viewports, which means 2 things : It's harder to manage in the UI than a single viewport
I am forced to put the content of my worlds as childs of UI content. This ties together the actual gameplay world and UI, making working with either of those harder than it should be

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

Instead of spatial nodes finding their world by finding their parent viewport, they instead find it through a new node called "world runner/manager" or something similar. This node's only responsibility is to keep a world running. Viewport's sole responsibility now is to render the content of that world either by being assigned the same world, or being assigned a camera. The later would be better, because it'd mean changing which world a camera is in wouldn't require changing anything on the viewport. If the viewport needs access to the world data, it can still get the world through the camera, since it inherits spatial.

The result is being able to instance and run multiple world, completely independently from the UI, and being able to render the content of any of these worlds with just 1 viewport.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Mockup : An example of the setup : Setup The world runner node : WorldRunner The modified viewport node : Viewport

If this enhancement will not be used often, can it be worked around with a few lines of script?

It's still possible to run multiple parallel worlds using multiple viewports, but it'd require making a whole system to manage multiple viewports, and worlds would still have to be childs of UI elements

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

This requires changes to how existing nodes and resources function

2plus2makes5 commented 3 years ago

This reminded me that time ago i also made a proposal that involved some kind of separation of the Viewport from the rest: https://github.com/godotengine/godot-proposals/issues/759

I don't know if i should open a proposal for this and maybe it's stupid, but after some thought i arrived at the conclusion that maybe there shouldn't be a Viewport node at all. Why?

Because at its core a Viewport(to not be confused with nodes that can visualize the content of the Viewport) is not an actual part of a scene, it's not an element of the game, it's not a gui, it doesn't help with collisions, ia etc, it's just what the GPU draws, it's like texture data, we don't make a Texture node and make its children all the nodes that use that Texture, there's no real need for a Viewport to be part of a scene, let alone having nodes attached to it.

In my opinion a good way to handle it could be to have Viewport settings in the project options, with a default Viewport always present and an eventual array of custom Viewports. In that case Camera2D/3D, ViewportContainer etc would have a parameter pointing to the Viewport to be used.

This way there would be a relative indipendence between nodes and Viewports.

I hope it makes at least a little of sense lol.

Xrayez commented 3 years ago

Note that get_tree().get_root() is the root Viewport. In Godot 4.0-dev, viewports were also renamed to SubViewport extending base Viewport class, so I doubt it's going to be removed as a node.

Viewport also allow to propagate input from the main loop down to the children nodes which receive _input() callbacks, as far as I know. In a way, the Viewport node acts like a medium between OS and the application.

Yet it is possible to use viewports rendering functionality without using nodes, as it's part of the VisualServer/RenderingServer API. Things like https://gist.github.com/clayjohn/80d9b1e52e1b9a23445504e85a8d7890 is a nice example of using such API for other use cases.

See also godotengine/godot#28816 which proposed to have nodes to create dedicated physics spaces, and there's an asset/plugin which showcases this feature via GDScript: https://gitlab.com/LeonardMeagher2/GodotAssets/-/tree/master/2D/SubSpace2D.

Godot even used to have unused and not exposed Space2D resource for a while, which is removed now: godotengine/godot#37264.

But in general, yeah I like the idea, but it's quite difficult to come up with something concrete at the moment myself:

I hope it makes at least a little of sense lol.

😃

2plus2makes5 commented 3 years ago

I'm glad it wasn't non-sense lol.

I don't know the implementations so maybe i'll say something stupid, but from what i see Viewport has functionalities that at least in my opinion don't seem to fit a "viewport":

A)Audio Listener: a Viewport isn't "physically" in the scene, it makes more sense to me to add a Listener node as child of a Node that visualize the Viewport.

B1)World: i think the Viewport only function should be to draw what the camera see, if we want different Viewports to show different things but using different layers in their Camera(like what i'm doing, one viewport shows the GUI at max resolution, and two other Viewports show the 3d elements at custom resolution, one show some elements filtered while the other shows the rest unfiltered) is not enough then adding a World parameter to the Camera(or some other solution that involves Camera, not Viewport) seems to me to be better.

B2)World: if we want to use different physics... why should we use a "viewport"?

C)Input: same

It seems to me that Viewport was meant to be more than just a "viewport", something like a custom "world" with its own graphics, inputs, sound and physics, in that case it think it could be more clear to have separate and focused "viewport", "physics", "listener" and "input" classes to customize viewport, physics, listener, and input, and then a class that represents a custom "world" with its own default viewport, listener, input and physics.

Ok that's enough, sorry for bothering you with this stuff. Keep up the good work!

Xrayez commented 3 years ago

See also discussion in Godot chat: https://chat.godotengine.org/channel/devel?msg=skH4fEXEEDZKjpKfR (OP is aware of it).

But in short, here's what the lead developer says on this:

reduz> in earlier versions of Godot you could override the world/space per 3D/2D node, but it made things really complex in a lot of areas, so it was restricted to viewport to simplify it reduz> also in most cases you can get away with just using collision masks, so even having separate spaces in a single viewport did not make that much sense for the most part reduz> I figured that if a game ever really needs this, you could implement your own nodes for this, which I guess its kind of what you ended up doing