-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create a Swarm/Mob/Flock/etc system for managing large amounts of entities #2380
Comments
I spent some time trying to get EnTT (amazing framework) to work as a module (for crowd sims) and would definitely appreciate an official solution.
|
@Ansraer Well the script is just the actions that execute in the linear memory buffer, nothing prevents you from putting a global script in the node or something they can interact with. |
That would solve 1, but I dont see how I could accomplish 2 and 3 with that. Unless you want to add barriers to gdscript? |
@Ansraer I have no idea honestly, I suppose when we are closer to implementation, if community actually likes this, we can see whether it's possible/worth implementing something like this (and how) or whether something else, more custom, should be used. |
Script in the update loop is likely to present a major bottleneck; two ideas come to mind for defining simpler script logic that will scale with a swarm:
A combination of both of those would suffice even for a simple character controller, and most likely the AI requirements of any swarm, if hooked into API calls - which could also allow triggering script if it's necessary to do something like compute some arithmetic, likely with some restrictions. The main consideration beyond that would be how much state is tracked by each entity, with the smallest amount being a single value that enumerates all possible states. |
Movement seems like the biggest issue for this since that often requires significant scripting per entity per frame. Compute shaders would be perfect for that, but is probably out of scope due to OpenGL ES support. One solution I could think of is that you can set a path the entity should follow, then the logic of that entity only needs to be updated whenever it has finished moving towards it's current target. It would be good to have some options for how that path should be followed too, e.g. steering behaviours: aligning movement vectors with nearby objects of the same flock, attraction/repulsion towards certain elements, avoiding collisions. |
@triplefox and @API-Beast A lot of work is being done towards optimizing scripting, so this should hopefully not be a problem at the time this is implemented. |
I kind of dislike this proposal. This resource, along with the associated system, look like a big carryall thing, which has several problems to me. While it does a lot of things, you will always with people having specific situations where something does not work as they expect or is missing a feature to work for their use case. This will also make it annoying to maintain. But I think its main problem is not here. I might be wrong, but I think you highly overestimate how difficult are the servers to use. So in my opinion, instead of creating an in-between solution between using nodes and using the servers, I think a better way to go is to make using the servers a lot more accessible instead. This should go through providing examples, demos and documentation. Some Nodes' documentation pages could redirect to their corresponding example in the documentation, so that people could easily replicate what they do in a node to a script (like the Sprite documentation would redirect to a page explaining how to use the rendering server directly instead). For the demos, we could go for a bullet hell game, an RTS or things like that. That would make it more obvious that you don't have to use nodes all the time to build your game. |
We had a "Bullet Shower" demo in 2.1 but it was never ported to Godot 3.0 and later. |
I think that the servers (plus GDNative) could already accomplish the same functionality expected of an ECS, the problem is that (as of 3.2) the servers dont allocate memory in pools/allow preallocating memory? And using RIDs seems to be slow since it uses a hashmap instead of just being an index to said memory pool. RIDs would also need some improvements to interfacing better with non-server api, because I remember trying to get a texture reference from a server handle and there was no way unless I made a copy of the image data and upload it as a new texture, which was definitely inefficient. |
I think this proposal would be better as an add-on in the asset library. Perhaps even an official one. When it comes to "needs to interact with everything that is there easily", I think we should make it easy to interact with those things (servers etc) from an add-on as @groud suggested. In any case, this is something we don't need for the 4.0 release, so I've added this to the 4.1 milestone (can be moved to 4.2/etc if needed later).
I think that's a great idea. It would be nice to have a simple RTS demo, we could use it to showcase things like navigation, minimaps, selection, camera ray projection, RTS style camera movement and zooming, and as you suggested, interaction with servers directly (to be honest, it's still fairly new to me). It may be better to make this demo for 4.0 only and skip 3.2 due to the navigation rewrite in 4.0. Bonus points if we can get terrain in Godot 4.0 and we could use terrain in this demo. (Further discussion on making a demo like this would mostly be off-topic for this thread so it can be continued elsewhere). |
Swarm systems are, more often than not, very specialized systems. I feel like the subset of games that could use this would be rather small. There are instances it would be useful, but the problem here is... you're going to have trouble with a "one size fits all" when it comes to "how does the swarm behave"? How do you interact with it? The time dedicated to this would be better spent on other systems that actually benefit larger groups of game devs. It's a good idea, for further down the line, when we are not lacking in more core features/functionality. |
I do like the suggestion of demos and documentation for servers, I would like to learn more about them. That said I would still really really like some purpose build solution for these types of problems because I wouldn't trust my own coding ability enough, and I need this for a game if I don't want to cripple it's feature set significantly. I come from the perspective that coding is an obstacle that's in the way of my creative vision. Something I need to overcome, not a fun puzzle to solve along the way. My experience with more low level code is that I waste multiple days fighting through obstacles to come out at the end with nothing useful. I'm using a game engine to take tasks like these of my already full task list as a solo dev, and my current solution for these problems would most likely just be, I can't do that. I bet I'm not the only one too. Just the only one who is willing to admitting that his glue code skills are probably not enough to make some of these features production ready. |
For those looking for documentation on low-level servers, I ported the Bullet Shower demo from Godot 2.x to Godot 3: godotengine/godot-demo-projects#588 |
@groud There is documentation on how to use the servers directly, as been around for a while as well as demos (which are not up to date I believe, though): https://docs.godotengine.org/en/latest/tutorials/performance/using_servers.html Still, this did not catch on. it's also still very hard to optimize with linear memory for cache efficiency for most end users. Additionally, with GDScript it's not even possible, so large part of this work needs to be done anyway. Using servers also is not that easy, they require RIDs and are too low level in many cases. Even if you do demos, the resulting code is not that simple for a large part of our use base. I suspect you are biased in this regard because you are a very skilled developer and contributor and know the engine well, but large part of the Godot userbase does not have this experience nor the time to acquire it, they just want to make games with as less hassle as possible. So, in the end, users still complain to this day that using the scene tree for lots of objects is slow and that there isn't a simple and fast way to create lots of instances for simple entities. This problem is real and it needs a solution. This proposal aims to be that solution.
This is not a problem, we always strive to support the most common use cases (the ones I listed I think are a good starting point), then leave the door open for users to implement whatever they may miss. Nothing new here, has been our development philosophy since ever.
This would be the case if this was something easy to workaround, or a rare use case (the common rules to make something an add-on). Unfortunately, it is neither and this is a very common problem among Godot users (plenty of complaining about performance with large amount of objects in Godot), for which it needs to be core.
You talk as if swarm systems were something standard, maybe they are but I was not referring to any of that I only used the word Swarm because it needs to be named somehow, but this proposal is not some sort of common thing and it's designed for a very specific problem in Godot. |
@Calinou the bullet shower demos is ok, but it's very far from being the most optimized form of something like this. As I described in my proposal:
I think the complexity that this proposal hides from users is probably understimated, it's not easy or obvious how to do a lot of these optimizations for a large part of the Godot user base, while all they may want to do is move a thousand bullets and see if any hit the player. So, if using servers directly (which by itself is far for being the most optimal solution) did not really catch on for most users, there are zero chances that something more complex will. We need a better way to simplify the "large amount of simple entities" problem. |
I'm sure it will work extremely well for certain scenarios, but I worry that it will be very constrained and limited. If the desired feature is not supported by this system, users will still be pushed into GDNative/Godot Modules in order to achieve the level of performance they desire. I recommend that we work on improving the raw performance of GDScript. How much further can we push the performance GDScript's design? Can we add new APIs to GDScript that support batched and parallel operations? Perhaps we can work on lowering the friction to using GDNative and Modules and increasing the adoption of that approach. I think this could have a side effect of educating the user base, which will help train the next generation of programmers to understand and contribute to Godot. This will benefit us because the user base will be able to contribute in ways that we ourselves cannot, including after we are all dead and gone. Imagine a very young person finds Godot and enjoys it's simple and accessible system. It's true that Godot is very easy to use. Now imagine if that child can find his or her way into the Godot source code. That child has the potential to become a prodigy. If we can channel the passion for Godot into c++, we can contribute to the education of people all over the world. This will not only benefit us, but will benefit the planet. In summary, here are some approaches we should consider:
|
@jknightdoeswork These things are planned regardless of whether or not this proposal is implemented (though, I would argue that improving GDScript and GDNative are vastly more important things that should be worked on before this proposal is considered). @vnen has already been working on rewriting GDScript and GDNative for the past year, hopefully this will include performance and usability improvements in addition to bug-fixing and a cleaner API. And of course, the community is encouraged to create libraries and APIs and distribute them via the Godot Asset Library (or by any other means). |
I'm glad that finally a discussion is happening around "swarm systems"/ECS/whatever you might call it. It boils down to this: I love the idea & love that you want it to be core Godot. But to add to @jknightdoeswork s points, I very much agree: If you ever end up tackling this, please consider ergonomics & also make this as powerful as possible. Don't just optimize it for "swarm" style games, sandbox & city builders, but make it a good option for using Godot in general. I think it would be well worth the effort! :) EDIT: Further reading which expresses my thoughts far better than I could: https://ajmmertens.medium.com/ecs-from-tool-to-paradigm-350587cdf216 |
@konstantinkopka ECS is not under discussion, this covered by projects such as Godex (see proposal) |
@jknightdoeswork the idea is to cater to simple and common use cases and then work from there, it is fine that more complex/uncommon cases are pushed to gdnative |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This is where I stand as well. I'd also like to brainstorm server APIs expansion, i.e could we add mid/high level server methods that do something in 1 API call instead of 5. Server API calls will always be the bottleneck with this system. Servers documentation and examples could be improved A LOT. I did build a huge simulation using Visual and Physics servers but the process was painful and at the end of the day I gave up before I figured out how to do rig stuff with servers. |
This is getting very offtopic. This proposal has nothing directly with ECS nor with servers. I think the proposal itself is a great idea, that could really help Godot move forward as an engine. Historically, general purpose engines (like Godot) were well suited for making platformers or shooters, this is because the medium complexity entity approach works well for these kind of games. However other genres, like tower defense or RTS games are significantly harder to implement, because they depend on more complex systems. ECS makes such systems more performant but not easier to implement, the same goes for Godot-style servers. You generally need some significant programming experience to implement such systems. A swarm system on the other hand could make implementing such systems really easy, without need for such advanced programming knowledge. Godot would be the only engine having such a system and if it is well designed would attract a lot of talented game designers. |
On the contrary, discussing alternative solutions and comparing them to the proposed solution is a part of the process. And while ECS is off the table, better API for servers is not. People have concerns that this porposal is attempting to be a one-size-fits-all solution, whereas extending servers would provide better building blocks for a more customizable approach. Groud also mentioned that this is going to be annoying to maintain. And I think he meant that this all-encompassing proposal will make it hard to draw the line and judge which parts are relevent for core and which parts are to be discarded and left for users to implement. Say, this is added as is and a user comes with a proposal to add Y to the new system. When the system is very spread on features, not as focused as Godot's standard "node does one thing" idea, it's harder to evaluate if user's proposal has merits, or is less improtant than an arbitrary list of features described in this here OP. And servers are granular but focused systems, so it's easier to appreciate where their core capabilities end and user expansions begin. So, no, talking about alternatives is not off the topic. |
It is "just" a more advanced (and maybe more user-friendly) MultiMesh node. It's really not all that radical. |
Can someone roughly explain to me how a setup for a swarm would look like in Godot? I get the feeling that everyone has a different idea of this system in their head. Here is a high level overview of how I thought it would work, on a simple example of a bullet that bounces off of walls. I create a single bullet entity with a swarm node. |
I think this proposal is going in the right direction. I also don't agree it should be left just as a server API. Godot is an Engine not a "just framework". Maybe I will sound a bit harsh, but sometimes I get the feeling that some want to shift from Godot Engine Project to Godot Framework Project. Server APIs should be last resort when the user needs something that exceeds common use cases, not a default way of using Godot. |
I feel like this Godot project I made a while ago may be relevant, it basically a demo project similar to the shower of bullets, which is a case mentioned in the proposal, in the project you can see as I previously said, you can use GDNative and handle everything yourself, getting a lot of performance. |
There is a typo in the URL; it should be https://github.com/thimenesup/GodotDataOrientedTest 🙂 |
Recently there is a game called Vampire Survivors. The game has a large number of rigid bodies. Is Godot capable of handling this situation without gdnative? With the advent of this game, I think this proposal is necessary. |
I've seen Vampire Survivors-like games being developed with Godot, so it sounds feasible. You may have to use various optimization tricks such as decreasing physics FPS and using interpolation, using low-level servers, using C#, etc. |
While not an apples-to-apples example, Defold has a plugin that could serve as a base for at least the higher level logic of this setting. https://github.com/dev-masih/defarmy it's written in Lua, so at least it's easier to read even if you don't use the engine regularly |
I like this idea.
I think it would be nicer if we had a swarmlet node that accepts child nodes. If we want to associate data with an individual member of a swarm, using nodes seems like the most natural way to do that in Godot. The engine would just enforce some heavy restrictions.
The editor would show in real time when a child node is breaking the rules. When the game is built, all the data in the child nodes would be flattened into a structure that is memory and cache efficient. Even if it's effectively a toggle and a bunch of drop-downs on the backend, I feel like "I want physics" should mean "add a physics node of the desired type" instead of "click the 'I want physics' toggle and select the right type from a drop-down". |
The way you describe those nodes as dataholders and the associates tree constraints, I think what you are after are Resources owned by the swarmlet node, more than full fledged subnodes. I'm not sure if a node can own a list of Resources though. |
You are correct. A list of resources + a script associated with a node sounds perfect for this kind of thing. You could even sidestep the swarmlet node entirely and have the swarmlet be a conceptual collection of an array of resources plus a script, which is closer to the implementation anyway. I think that this would benefit from a new bottom panel. It could provide a list of the resources in a swarmlet for easy access and make it easier to manage many different swarmlets of the same structure. For example: a statue that you can shatter. Each swarmlet would have collision and a mesh renderer, but the mesh and collision shape would be different for each one. You wouldn't gain any bonus from instancing, but you may still benefit from the cache coherency. If we wanted people to use it like this we would also need a "load into swarm" toggle in the importer that loads all of a model's individual mesh and collision shapes into swarmlets, but that's besides the point. Doing it this way, it would be nice to be able to promote a swarmlet to a full node tree with a non-swarmlet script, and visa versa. Defining the structure of a promoted swarmlet could be another job of the bottom panel, and the developer would understand that anything other than this structure can't turn back into a swarmlet. Imagine you have an RTS and you can possess units. The unit is a swarmlet until the player inhabits it, at which point it becomes a node tree with a character controller and it stops listening to the swarm manager. When the player leaves the unit it's either welcomed back into the swarm or stays a node tree. Developers are warned if they can't go from node tree to swarmlet. The logs would show something like |
I've given this some more thought. ResizingIdeally a high-performance component like this would allocate once when it's loaded. The swarm would have a max size set by the developer and so long as you stay in this max size you never have to perform another memory allocation. Resizing after it's loaded could mean one of two things:
Of the two, I think the second one is better. It's simpler and faster when iterating. It's a tradeoff. Users who want their swarm to be fast should keep the number of resizes to a minimum; ideally 0. Shared and Unique DataFor all swarmlets in a swarm, there is shared data and unique data. Shared data is stored in the swarm manager and may be instanced, and unique data is stored in the swarmlet array and won't be instanced. It's up to the user to decide what is shared and what is unique. Take boids, for example. All boids share the same art, but the position and velocity is unique. The shattering statue example would have a shared texture, but the mesh data for each fragment would be unique. A squad of soldiers could have a single velocity and position as a group, but a different offset from that central position. From a performance point of view:
That being said, we don't actually want to store unique art data in the swarmlet array. For the sake of performance we want to store it on the GPU and just send the position/rotation for each datum and let a vertex shader do its thing. |
This comment was marked as off-topic.
This comment was marked as off-topic.
@ysypnbh Please don't bump issues without contributing significant new information. Use the 👍 reaction button on the first post instead. |
What about support for something like this? It would be nice if we could write something like this in godot without getting our hands dirty in c++. |
@Shadowblitz16 Support for... voxels? There's already some tools that provide support for voxels like Zylann's godot_voxel tool https://github.com/Zylann/godot_voxel . Also idk what that has to do with a swarm system |
You guys are building the swarm system due to speed limitations of gdscript and C# right? Just adding a swarm system to cover entities only fits a very specific use case. |
Describe the project you are working on
Godot
Describe the problem or limitation you are having in your project
Godot is designed to be easy to use as first priority. The Scene system in Godot (Scene and Nodes) are designed for maximum flexibility as well as simplicity. This works great in most cases.
In some situations, however, this can be too much when dealing with very large amount of objects (passing the thousands, or dozens of thousands). While in most cases this is not a common case, some situations require large amounts of elements to be processed, such as:
These situations have different requirements than what you often find in most games, as they consist of large amounts of simple entities, rather than smaller amounts of complex ones. Again, Godot scene system is designed for moderate amounts of complex entities (as this is what is required in most games), but proves to be overkill for large amounts of simple ones, as lack of cache efficiency and the complexities of the tree-based structure slow things down.
The only way to do this in Godot right now is to talk to servers directly or go via GDNative, but this is not accessible for most Godot users. Other game engines rely on ECS to solve this (Unity is working on it), but this is also an approach geared to more experienced programmers, whereas Godot aims to be a very easy to use tool where someone without high technical education or lots of experience can still solve the complex problems inherent to game development (then Again, for those more experienced, or more complex problems, GodEx can be the solution).
Describe the feature / enhancement and how it helps to overcome the problem or limitation
What I propose is creating an alternate way to deal with large amounts of simple entities. It could be called "The Swarm System". A system would be created in a Resource and edited in the editor. You would visually configure how you want your swarm to be basically ticking boxes such as:
The script (at least GDScript and and C#) will probably need to support something extra internally, as its data will need to stored contigous in memory in order to be processed. C++/GDNative will expose this also so other languages can support it.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
There will be a SwarmFormat resource, which can be edited and configured, saved to disk or similar. Probably with a bit more advanced options whether you want this to be processed in threads (more entities at the cost of being more careful with threads).
Additionally, there will be a Swarm node that will allow setting swarms and control their spawning and execution via API.
A common question to this may be, what if you want to have slightly different objects in a swarm? For this, you can either create multiple ones, or just do whatever you need by code in every swarm entity at the cost of performance/flexibility.
Again, if more flexibility is required, users can use an ECS system or simply write their own low level code and interact with the servers directly, but the idea of swarms is to cover the vast majority of cases where you need this performance optimization and still keep it easy to use and well integrated to Godot.
Swarms will be able to interact easily with nodes and vice versa, for greater ease of use.
If this enhancement will not be used often, can it be worked around with a few lines of script?
Is there a reason why this should be core and not an add-on in the asset library?
No, this is definitely core, needs to interact with everything that is there easily.
The idea of this proposals is for community to discuss and give feedback on this idea!
The text was updated successfully, but these errors were encountered: