Creating the illusion of a bustling busy city. (AI population)

I’m trying to figure out the best way of populating the streets and some buildings with super simplistic AI just to bring a little life to the environment. So far I’ve created an AI blueprint that uses event ticks with delays and some simple logic to find waypoints that I’ve placed all around the place and to find a different one if they get stuck trying to get to it or they reach it and stop. And that works reasonably well with a few dozen actors, they don’t get stuck on each other too much and they seem like they’re actually wandering about and not just randomly swapping direction mid stride.

Just a glimpse at what they’re doing (nothing happens, they just walk):

This is much higher density than I want to have, just to test it. With lower numbers they are much less likely to get stuck on the stairs, but it’s still a bit of a problem.

For some reason, the AI’s are causing a spike that slows down my framerate every 1 minute interval. The more AI’s I have the bigger the spike and I can’t think of anything that would happen for all of them at exactly 1 minute intervals. They do all change move to waypoints between every 30-60 seconds, but that’s spread out with a random float between those values for each individual instance of the AI. But that’s barely noticeable unless I have well over 100 AI’s moving about. Which brings us to my next performance issue.

Running them all like this is somewhat heavy on the resources. There is little difference whether I’m using an animated skeletal mesh or a simple capsule moving around, so having lower LOD stuff probably won’t help. I don’t know if it’s the blueprint approach I’ve been using that’s inefficient or it’s just a thing that’s supposed to be slow. I can’t think of many games where you would have hundreds of actors moving about anywhere. The closest existing example of what I want to achieve that I can think about is Hitman: Blood Money Mission 6. Where there’s a parade going on in the streets which are full of what seems like hundreds of people. (Hitman: Blood Money Walkthrough Mission 6 - The Murder of Crows - Pro - SA - YouTube)

I’ll have to do some kind of culling and spawning of actors that are in visible range of the player, but I’m unsure what the best way to do that would be. Just off the top of my head, I’m thinking maybe either trigger boxes in the level that detect the player and “move” the population along with the player or some kind of giant trigger box attached to the player that deletes things that exit it and spawns new ones to maintain a proper number of actors in the world. So any better suggestions are definitely welcome.

And one final thing, even though my primary goal now doesn’t involve killing all of my wandering civilians. Is there any way to stop the event tick from trying to send any signals after I’ve killed it (ragdolled and stopped the animations on the character without destroying it)? I have tried running the initial execute line through a branch that checks if it’s dead or not, but it sometimes still goes through. (no idea how) And once the character is dead it doesn’t need to check if it’s dead or not every tick. I feel like that could be handled better.

Any questions, suggestions or ideas are very much welcome, it really helps to have others look at these problems from their perspectives.

Looks great. But one suggestion maybe.

I have found that doing everything that happens every frame/tick in c++ makes a big difference performance wise.

So basically I hash out what I need in blueprint, then convert that to c++ on things that happen every frame/tick. And let things that happen every once in a while in blueprints. If a thing only happens once every few seconds/minutes, it doesn’t really pay to take the time and convert it.

You might want to look into flocking or “boids”. The canonical source is here.

Essentially, you combine a few simple rules, and apply them to each actor in a large group to get interesting behaviour for the overall group. You can use it for birds flocks, schools of fish, crowds, or zombie swarms. You get realistic group behaviour without having a heavy duty AI for each individual. Each individual in the group is pretty dumb, but they create an illusion of intelligence when you get a lot of them together.

There is an open source implementation you can take a look at called OpenSteer. It’s in C++, but you might be able to look at some of the rules they are using and implement them in Blueprints. Download the executable and try it out. Take a look at the “Pedestrian” plugin, in particular. They have pedestrians that follow a path, avoid obstacles, and try to avoid running into each other.

Here’s a screenshot of the Pedestrian plugin running:

a0eee9a01c5d85fde5ba38bf9af9c6f7e912c703.jpeg

I have 450 actors running around the scene, and my framerate hasn’t even noticed (there is a bug in the code that overflows a drawing buffer so I can’t go much higher than that, but it goes about the same speed with 450 as it does with 10). It is being rendered with simple line graphics, but it shouldn’t be too difficult, theoretically, to just hook the code to control UE4 actors.

Obviously, this is all very high-level and would take a lot of learning and work to translate it to UE4/Blueprints (and to be efficient it would almost certainly involve writing some code in C++ and hooking it into Blueprints). But this is an approach you might want to look into–as opposed to implementing a full path-finding AI for each actor in the crowd.

I created a custom tick event that only fires once every X amount of seconds, so none of them are actually ticking every frame now. Which did increase my performance somewhat, but it’s not exactly suitable for masses still. Perhaps it’s the actors trying to navigate the navmesh itself that’s the relatively slow process? In which case it would make sense to not use that and create some kind of different navigation method that’s better at being scaled up massively. The flocking and boids are interesting. Especially for large dense groups moving around. I’ll see if I can add some of those basic rules in blueprints for avoiding others in their path without ticking something every frame.

I’m still confused about getting a spike that increases my frame time for one frame 3-4 fold once every minute. It seems to be AI related, but none of them actually do anything at that interval.

I’m just thinking out loud for the most part, but I read some information about how actors get culled and spawned in L4D2 based on the player location to save on resources. Which is of course very good in there, with the zombies spawning out of sight and despawning when they’re too far away and at quite short distances because the general view distance is very low. Better creating the sensation of a horde with fewer actors than just throwing huge numbers at the players at the cost of performance. But does anyone know how that’s generally done in a more open world game with long view distances (such as GTA or Assassin’s Creed) They do seem to sort of fade in in the distance when the player is moving, but I’m not sure if there are fixed spawn points that activate within range or is it just completely random as long as some total number is maintained. Some degree of predictability would be needed for spawning special AI’s such as guards or shopkeepers/quest givers, but completely trivial AI’s could just be completely random. Also how to maintain persistence in the case of special spawns to prevent guards you’ve killed from respawning if you move just outside of range and back in again.

Bohrium, remember that in Hitman you are at his eye level. This means that, surrounded by the crowd, you don’t see that you are only ever surrounded by (I think) 256 (clipping, which is important, they didn’t get to be properly solid until the very similar Kane and Lynch nightclub scene) figures. The rest are stripped out by culling, as you have said. However, they are so close to him, you don’t see the empty bits of the street. This close-crowding is the key, so you don’t see the spawning/despawning.

(From a higher vantage point, they are LOD-ed down so allow for more people.)

I would use the nav mesh to keep a group on one floor, away from chokepoints. You would have a separate nav mesh on the other floor, with another group of NPCs. You then have another nav mesh on the steps, for a group to go up and down the steps, small enough to avoid choking the area, with a bit of overlap so that it looks like people are walking around the whole level, rather than just sticking to their prescribed area.

Sorry, having reread your later post, I’m not sure if this is what you were asking about. But, hey, a post is a post. :slight_smile:

P.S . If you have the K&L: Dead Men game, try looking at the nightclub scene. That might give you some more pointers, as it has a similar layout to your level, with narrow stairs and corridors.

If you’re creating and deleting actors, check the garbage collector. It’s better to create your AI actors once, then reuse them, instead of deleting and spawning multiple times.

Separate the AI intelligence from the UE actor. This is the point of the controllers, you separate the intelligence from the physical .

Hello,
if you do a simple walk from a start to an end, you may can teleport them to a new start instead of destroy them so you don’t change mob quantity except when there is a kill so then you can add a new spawn event after the destroy one which you can choice the starting spawn point.
And by choosing starts and ends at hiddden places it may looks like a normal appear disappear
and maybe by using the parent class for random walk but adding a random child spawn with a different mesh / instanced material for the actor as jcoder said, you’ll have always a lot of people walking to somewhere looking different and not apparently random walking.

not sure i’ll help but, in hope ^^

Please I need it, you could not put the project with the script to download, so I get it?

From the video (don’t know if you’ve got a more update one) but it doesn’t really look like a bustling city, just a lot of people wondering around (pretty lost). I know you said basic AI but just having something wonder around is too basic. One thing that could help with performance is possibly idle time. If you have a set of needs such as hunger, thirst and social you can how them wonder around to spots that fill these needs. This also allows them to have some idle time where they just play and animation reducing the number of calculations at one given time. This would also add a little extra depth in terms of their behavior.

This was literally as basic as I could make a bunch of people wandering around, just to see how many of them I could run like that. I didn’t really consider the performance benefit of having them stop and do things, but I was planning on making them act more like humans eventually, once I nailed down a reasonable way of getting the sheer numbers I wanted. I don’t think I’ll go as far as creating them individual desires to drive their actions, but rather make it a chance to sometimes stop and look at something or have a seat on a park bench or go buy a hot dog from a stand. But yeah, if I had a decent percentage of them doing other things and not trying find paths to places, it should give me more room to work with.

So far I’ve just had them all spawned in from the editor before even playing and not deleted or respawned anything. But yes, moving them around is the much more sensible option.

The ones in Hitman seem to be in constant motion in a pre-designated area, which means if I wanted to fill a room with similar ones, I could just make them move forward at all times and randomly change direction when they reach a wall. And most of the ones in Kane and Lynch don’t really seem to move at all for the most part. (Just wobble around their origin dancing, which could just be from the animation.) And when the panic mode triggers they just run in random directions on the same floor. So perhaps the best solution would be to mix and match things that “bounce” around (that should be considerably more efficient in large numbers) and actual AI’s that are trying to go somewhere and do things and ones that are just playing some kind of animation while not moving. Just having them move in a random direction per tick until they hit a wall is slightly faster than a pathing AI with blueprints, but I should definitely try recreating it in C++ to see if it gets considerably faster.

All this has made me wonder about how management games (like rollercoaster tycoon) have thousands of individual people that walk around and make complex decisions. (about whether or not to go on a ride, or if it’s too expensive or if the scenery around the ride isn’t good enough or if they want a balloon or not) Even if none of them are rendered on screen, they all still need to do things all the time and not just inside the scope of your visibility. Of course they can omit a lot of the things necessary for what I’m doing, like collision detection and avoidance of others during their pathfinding.

Frame rate spike could be due to VRAM become fully loaded and then it will cause what we call texture trashing - lots of textures are getting swapped between VRAM and RAM and this may what cause the spike. The FPS spike is normally very drastic… eg FPS can suddenly dive from 60 to 1-2 fps… and it stays there for a few seconds and then resume the normal FPS.