I have a city with 850 characters. How to optimize it?

Hello,

this is a single player game. The only city of my game should have 850 NPCs. The NPCs are around 20.000 polys, maybe I can reduce them. Draw calls are optimized with atlases/arrays of textures. I would like some help with how to make it.

I thought of some optimization techniques:

  • The city would be divided by neighborhoods. The streets that limit with each neighborhood would have a overlapping box that when the player gets overlaps the neighborhood that he is entering loads and the previous neighborhood’s NPCs despawn. This would be implemented for example with 6 different neighborhoods, so aprox. 850/6 = 140 characters per neighborhood.

  • Not all characters of a neighborhood would be visible at the same time. Since many would be in their homes, therefore culled. Let’s assume that at most half of them are visible at the same time: that’s 70 characters drawn.

  • Not all characters are close to you. The LODs would kick in. Say that at LOD 0 you would have at most half of the loaded characters: 70/2= 35.

What other techniques could be applied?

My biggest concern is with the Character Movement Component, since I do not know C++ and it has over 1000 lines of code that need to be optimized. My character’s logic is simple and doesn’t need all of that. Any good tutorial on how to modify it?

For crowds you could go the way that the matrix demo does it through static meshes animated through vertex animation textures. The crowd ai is animated there through the mass ai plugin but that is more complex and still probably in the experimental phase (could be production ready, as of the 5.3 docs you no longer see the experimental flag)

use sublevel streamaing and activate/deactivate the NPCs upon loading or unloading.

I need the NPCs to have some sort of logic to them since they have to be interactable. So that is not an option. I just thought of another optimization:

  • Deactivate certain bones in certain LODs. So for example from LOD 0 all would be active, but LOD1 would have the fingers deactivated, LOD2 the elbows/knees, etc.

Would this be similar to just despawning them from their blueprint? So when I enter a certain area the NPCs from that area will spawn and when I get out of it they will despawn?

A lot of tutorials regarding mass ai

I know that in the matrix demo they also replace the close ai’s with proper characters with extra logic (they seamlessly blend them from animated static mesh to skeletal meshes)

no, it would be like a physics object in or our of sleep state. you spawn it sleeping, then it will get woken up upon e.g. streaming in or getting withing an overlap sphere around the player. then upon end overlap of the sphere or streaming out you put it back in the sleep state again. that way it does not respawn from it’s start location, but remains where it was when put back into sleep last time. thats more organic/lively than spawning from the same start location.

@Vollgaser

My characters have different spawn locations based on the time of the day.

For example between 9-12: spawn at the fields and work
12-14: spawn at eating place
etc.

So they follow a schedule. So their spawnpoints are not noticeable.

Do you have any data on how both ways to do it compares? The loading/unloading with respect to spawning/despawning?

I’d put the “brains” of the occupants aka their schedule and checking tasks in a separate thread based on FRunnable and workers.
That way they can be doing things virtually even when they are de-spawned and invisible.

I’m not familiar with FRunnable, any good tutorial?

How I did it was I have a clock blueprint that divides one day into 10 periods. At each period a boolean is activated. For example from 12h to 14h we have Midday boolean =true. Then I made a component blueprint which has the schedule and it’s added to the NPCs blueprints. This component activates or deactivates certain behavior based on the boolean of the clock that is active.

Also, if they are despawned, it doesn’t really matter what they do. When they spawn again according to the world clock they are doing one thing or another. I could just completely despawn them.

Its pretty straightforward.
Just be sure to check if the gamethread is ready before pushing updates to the game world.