Well it's worth pointing out that I have 300 villagers so far wondering about using this code so I've been poking at it a lot I thought multi-threading might be a quick and dirty way to deal with my low FPS problem but it looks like I need to take a more considered approach.

Errr ... this may be a dumb question, but does that mean that there are 300 threads, one for each villager ?

    Pixophir LOL I don't know, I'm very new at this, but I guess yes? There's one script for each villager anyway, are threads supposed to be for entire nodes/used once?

    Instead of running a thread for every villager, the opposite might be better: Let one Manager node handle all villagers in the scene. You'll get the following advantages:

    • Manager can possibly skip calculations for large amount of villagers (because they are too far away from the player)
    • Manager might be able to reuse calculations for villagers in the same chunk/cell
    • Manager might be able to simplify calculation. If a villager is in a non-visible area and is supposed to "follow the player" you may want it to pass through walls etc. until it is closer to the player character. Players won't notice the difference.

    Also as a side note: Creating a single thread is very costly. That's what you do, if you have a script creating a single thread on each villager. It's kinda like ordering screws: Instead of ordering 1 screw, another screw, a third screw,... It's much faster to just order a box with like 20 screws or whatever.

    A manager can help with that too if really needed. Because the manager knows how many villagers there are. So instead of creating one thread at a time, it can create a bunch at once. Or it can run all the logic for all villagers in one single extra thread, that's always running in the background. Multithreading isn't easy to wrap your head around at the start. And honestly so far I only needed it on very rare occasions with Godot. I'd recommend to try looking into optimizations without mutlithreading first.

      MartinSenges Well it's handy that because I technically already have a manager node and that's to deal with things like spawning and hierarchy children among other things I just wasn' planning on using it the way you describe. This is the first time I've looked into optimising like this so it would be great if people could throw some resources and relevant documentation my way.

        Lethn To be honest I don't have any resources on that at hand currently, especially on Godot. This is stuff I picked up when I was still working with Game Frameworks like SDL etc. I'm pretty sure Handmade Hero covered this topic (or adjacent ones) at least partially in some video. But those videos are probably too hard to digest, due to their number, length and focus on C++.

        This is probably the best book on multi-threading. "C++ Concurrency in Action"

        It would be good to learn if you are serious about programming, but it may be a little advanced and not needed for a simple game.

        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.