I second that.
And that you should not have problems with C++17 and the STL.
I second that.
And that you should not have problems with C++17 and the STL.
Been thinking and maybe I should look more at techniques like object pooling, but I'll have to poke around some more at the various optimisation techniques.
Your use-case doesn't merit threading, it slows execution time down. It is also a case of premature optimisation, aka "the root of all evil".
I think it is good advice to first finish the game and have all planned features realised. Then think about optimisation, of which concurrency may be a part. And never optimise just like so. Always profile the execution with timers and objectively identify the parts that use up most of the time.
The tools Godot offers in GDscript are very limited anyway. They don't offer atomic (indivisible) operations for example, that may be better for this case, but I don"t know your project.
I find the suggestion of a manager node a good start. There all the villagers are in one spot. Later on, if villager movement really is the crucial point as identified with profiling, you can still think of concurrency.
Just my 2 cents ...
But of course, if you have the time to play with concurrency, then why not :-)
The problem is that with the 300 odd villagers I have in the game now it's chugging away at about 30fps so I don't think you can really make the argument of 'finish the game' in this particular case. I do think though that I need to look up more optimisation options beyond just multi-threading so I'll get back to researching on that. I plan on having something of a global villager count limit regardless that people can adjust for the sake of not killing lower end PCs, but if I can get a high number of villagers in the game and have it working smoothly I'm going to attempt it regardless.
But does that game really need 300 villagers? Or at least on screen at once animating?
Even AAA games like Cyberpunk 2077 or Assassin's Creed rarely have more than like 50 - 100 character one screen at once, and this is heavy for them.
cybereality I'll need to have a think about it all I guess, it's very much a kind of city management style game at the end of the day, so there does need to be 'crowds' kind of like with settlers and stuff like that. I wonder how Tropico and City Skylines does their people rendering because that's something I immediately think of as a modern day example. If I can have it not rendering stuff off screen is that something possible for the sake of optimisation? Might be something to look at as well, lots of methods.
For the record, the villagers play a big part in the gameplay, you can pick them up and throw them among other things.
And these games exploit all kinds of things, like hierarchical data structures, instancing, and whatnot.
With the right planning and the right game design one can render millions of objects without multithreading.
Edit: ninja'd :-) Yes, I think you need to rethink the game design, and write down on paper how exactly these things interact with the player, what their goal and objective is. With that we can certainly give more concrete help.
'nother edit: there's a lot of information on crowd rendering. I personally have not been there yet, but searching "how to render a crowd in a game" gives a lot of hits.
https://developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-2-animated-crowd-rendering
Of course, you will have to adapt that to Godot, and GDScript may be too slow. You will have to profile if you want to know which solution is better for your case. Can't say that often enough.
Just had a thought of a great example actually of the kind of thing I'm looking at.
relevant timestamp: 13:00
In Startopia you can have hundreds of characters on the screen yet it still runs smooth as silk especially for an old game and as you can see the character can be somewhat interacted with but also have their own animations.
Lethn The problem is that with the 300 odd villagers
I also want to make an agglomeration with at least a million characters… all with their own personalities… but I guess to start with a village with a dozen inhabitants maximum, gradually increasing the number.
The "anima" from AXYZ design works with a large number of people. Maybe they have something interesting to look at. There used to be even a free trial version.
For large crowds it might also be worth looking into Niagara. It's Unreal, but they do provide you with a lot of information on the general approach:
[
It might be possible to implement something like that in Godot 4, but it would probably take some C++ to write such a system. Maybe one or two of their suggestions is already enough for your case. Only commit fully to this approach, if everything else isn't enough. At this point this is more R&D than straight up game design, so you'd have to spent a lot of time figuring out what creates bottlenecks when using Godot and how to avoid those.
Now that was really interesting to watch, it's also the exact scenario that I've been dealing with and I've already identified some points for optimisation that I'll work on now.
. Navmesh movement is happening constantly, I could reduce the strain on the engine by having a timer in which I planned to do anyway because having the villagers walk around continuously is unnatural
. Code not within the camera view does not necessarily need to execute could potentially have very far away villagers be completely static until the player starts 'seeing' them in the camera
. Haven't done a proper culling implementation yet, should look into that as it would likely make a major difference for performance, will need to look at the camera view specifically for that
. Will also explore using sphere occlusion culling for the villages because I bet that would help things massively if I can get rid of that unnecessary stuff when it's at a distance
MartinSenges For large crowds it might also be worth looking into Niagara. It's Unreal, but they do provide you with a lot of information on the general approach:
I browsed hastily and may have missed something, but I didn't see individual character movement — everyone walks in a crowd, sometimes except for literally one dude. There's already such a thing in Godot.
Lethn . Code not within the camera view does not necessarily need to execute could potentially have very far away villagers be completely static until the player starts 'seeing' them in the camera
Those villagers who are not in the frame at all can not display, and load them only when the camera gets close to them.
Just found an excellent video on these topics specifically for Godot he even does a bit on the occlusion node which is something I was a bit baffled by.
The big thing for me is that I need to have the villagers be interactable, so you'll be able to pick them up and throw them among other things, time for some tinkering.
Tomcat Didn't have that Godot tutorial on my radar, so thx As for individual character movement: I'm not too knowledgeable about Niagara. But I think individual character movement is something you want to avoid with that system anyway. Either you split you crowd in a way that each group walks into a different direction or you make the code so generic that it keeps up the illusion of individual movement (the player avoidance example shown in the video + more stuff). Probably even both approaches.
Maybe there's also a need to swap out a crowd villager entity with an individual villager entity during gameplay (and back of course). Don't know haven't made a game with that kind of complex system yet
Lethn The big thing for me is that I need to have the villagers be interactable
This was done in The Sims (2-4). By the way, in The Sims 3 there can be several hundred residents.
MartinSenges But I think individual character movement is something you want to avoid with that system anyway.
The implementation of crowd movement is done in anima, there you can see that the residents walking in the same direction have different speed. But I do not know what technology they used and whether it is possible to apply it in games.
The optimization section mentions multithreading.
Just had a very interesting eureka moment, without the animations, the FPS jumps pretty significantly, it almost double, so it looks like that's what I'm going to have to look at optimising the most is how the animations are being played through the code, will need to have a look at these methods when I'm in a better mood for it. The animations seem to be confirmed as hitting the performance the most.
I wonder if there's something I can do about the way the navmesh is dealing with the code? I'll have to have a look at that video again myself.
So really the conclusion is that instead of doing multi-threading it would be a better idea to see if there's a way I can instance the animations that my villager has to make everything run smoother instead of the GPU trying to render everything all at once? No wonder I'm regularly hitting 30fps.
Edit: I'm also seeing that I guess having however many agents all on screen at once will mean that it's simply not possible to play the game above 60fps except if someone happens to have a really powerful PC which is interesting, will have to look at how much I can tweak things.
MartinSenges Maybe there's also a need to swap out a crowd villager entity with an individual villager entity during gameplay (and back of course).
That would be my first go-to as a solution to try for this.
Lethn So really the conclusion is that instead of doing multi-threading it would be a better idea to see if there's a way I can instance the animations that my villager has to make everything run smoother instead of the GPU trying to render everything all at once? No wonder I'm regularly hitting 30fps.
So don't play bone animations for any characters that aren't visible to the player at all. Pause the animation playback. This might not even be limited to characters outside the view frustum but also characters simply too far to be clearly discernible on screen. Also characters sufficiently far away from the camera/player vision can probably utilize lower FPS animations. Less bones per skeleton should be less demanding but also less keyframes per animation track and lower fps. Try and take advantage of a combination of these.
Let me think more on how to actually implement all of this, would this be similar to object pooling? I have the villagers wondering about as 'background characters' almost until they're interacted with through whatever action the player takes? I think just because of the nature of this game it will probably be a performance hit no matter what I do. If for instance the player decides, yeah I'm going to set the whole village on fire the villagers will need to be interacted with as I have panicking animations and so on as well, lots to consider.
Maybe have the villagers object pool at a certain distance like with the occlusion culling to ease off the rendering? No sense wasting processing power on something very far away the player can't interact with anyway. Just thinking about what I could do to implement this relatively quickly.
Ahaaaaaaaaaaaaaa!
https://docs.godotengine.org/en/stable/classes/class_visibilitynotifier.html
This will come in very handy! I would make use of tags with this so I can enable/disable specific node components and pause the animations among other things.