Wave Based FPS Game lags heavily after Wave 6/7. No Event Tick used, Frames go from 120fps to 50fps from wave 1 to wave 10. What can I do to improve performance?

Hello! I have a Wave Based Horde Style Boomer Shooter FPS game. I’m currently trying to optimize it for a steam demo build i’m releasing soon. I get some serious lag around wave 6/7 and it just keeps getting worse. I was told to do a dump hitch test so here are my results of it: DUMPHITCH Test - Pastebin.com . I noted that I went from 120fps constant to 50 fps constant after 10 waves of enemies (220 enemies spawned over the 10 waves). I used 5 different weapons while doing my test. My frame/game/gpu draw went from an average of 8ms on begin play to around 20ms and i was well over my 70% UNIT graph. Obviously the game runs better out of editor in packaged builds, but I still see the frame drops heavily after the 6/7th Wave. I have no Event Tick nodes in any of my AI and use alot of BB and BT instead of BP for the AI. My weapons are mostly hitscan and use minimal projectiles (the smgs use the most but even without the smgs the performance seems to be just as bad).

What would y’all recommend doing? I would really enjoy players being able to get to Wave 50 and not have massive performance drops…Thanks!

I would just play it in editor and watch the actor number to see if it just keeps going up ( which I suspect ). After it has risen for a while, F8 and take a look at the actor list in the outliner. I think something is not being destroyed correctly.

So i just did another 10 wave test like this, and these are the results:


my actors did go up, that is due to the suicide bot explosion bp not deleting, but fixing that didnt improve the performance of the game. it still goes up even if the suicide bots dont explode.

edit:

did another test run with the suicide bot explosion actor actually destroying itself and the performance did not increase…

Well, the only thing you can do, is keeping profiling.
What’s taking the CPU? It’s gotta be something! (Or something’s taking the GPU, and the CPU ends up waiting on the GPU.)
Use all the different profiles, and look for bottlenecks.

Well, it was a good theory :smiley:

Another easy thing is cutting chunks of the functionality out ( disable auto-save ). Just keep chopping large chunks until you find a pattern. Then focus it down…

Seeing the game logic taking up most of the time woulnd indicate that some functions are eating cpu cycles.

Do you have some looped timer driven events or recursive functions that could be stacking reducing performance?

The profiler could show which function 8s the cause of the slowdown. Maybe some nested loops?

A get all actor of class would also slowdown more each wave gathering more instances.

there is no auto save.

1 Like

Auto-save in editor …





heres some more profiling. it doesnt mean much to me tbh…im really new to this side of unreal. does anyone of this help? what profiling commands can i use to help find this one leak specifically?

turned off already

1 Like

I’m not saying that’s causing the problem. I’m saying take a level and hack out huge chunks of functionality until it works ok. Then go back and only hack out half, then repeat. Like that… :slight_smile:

I was referring more towards unreal’s insights

It has a more granular approach. Though you have to record your play session through a command and then load it up in the insights (really wish they would put this in the UI finally)

i did insights earlier, but to be honest, i didnt get anything out of it. i mightve done it wrong haha.

UPDATE:

I spawned the 220 enemies via the editor and killed them all. I had about 30 fps when they were all spawned in, but the more i killed, the better my performance. When I got to 0 enemies left, my performance was perfect. This leads me to believe its probably the Wave Based Spawner BP causing the problem. I don’t know why though. Can I post the BP in here via BlueprintUE (pastebin for blueprint)?

Sure post it. It might shed some light on where the problem is.

Main Event Graph:

Get Wave Variation Function: Get Wave Variation Function posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Initialize Function: Initialize Function posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Get Random Spawn Point Function: Get Random Spawn Point Function posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Check If Enemies Are Defeated Function: Check If Enemies Are Defeated Function posted by anonymous | blueprintUE | PasteBin For Unreal Engine

Theres all the wave based spawner bp

I didn’t code this thing, an old dev who is no longer apart of the project did. I didn’t question it because it seemed to work, but the performance is definitely not acceptable.

Ok so looking at the spawn mechanic I see you are using spawn Actor in a loop. Perhaps you could use an enemy object pooler. You will get a huge impact on gameplay spawning so many actors.

Take into account that the engine is probably still cleaning up a 100 or so enemies from the previous wave (the don’t get cleaned up as the die but get garbage collected at intervals)

During this time you are asking the engine to spawn in another 100 or so actors.

I’m guessing the construction phase of all of them is probably tanking your performance.

Instead of destroying an active deactivate it and put it back into the pool (an array), and when you need it again then just grab it from the pool, reset it’s health, set it to alive etc and put it on the battlefield.

Spawning many actors at once and keeping them in memory is cheaper then constant spawning and destroying.

OFC internal logic of enemies can also impact performance. Do you have central logic that dictates their actions as a swarm or does each have it’s own ai controller?

sweet, its good to know where the source of the bad performance is coming from for sure! thank you!
do you have any good tutorials you could recommend for an enemy object pooler? i’ve never made one so i dont even know where to start.

Currently the game only spawns 4 AIS in via the Wave Based Spawner, but I have more AIs. One is a test dummy bean AI that just used BP chase player and does nothing else, it wont be in the final game, and won’t be in the project any longer as of today. The other three AI the Spawner spawns use the same AI Controller. I have another AI Controller for another enemy, but he doesn’t spawn in with those enemies yet. Should I make them all have the same AI controller?

There are many object pooling examples on youtube

https://www.youtube.com/results?search_query=unreal+engine+object+pooling+

A pool at begin play spawns a set of actors (example 150).
All start as deactivated, all are added to the available pool array (a variable in the pooler actor)

A pooled object should have 2 functions

  • an form of activation (resets life, set visibility to true, sets transform, enables collisions), removes itself form the available pool array in the pooler actor (or you can have an internal bool flag that “available” set to false )

  • a form deactivation (sets visibility to false, sets collision enabled to false, adds to array that holds available actors or sets its “available” flag to true)

The available flag can help to not cause memory fragmentation from constantly shuffling the pooler array elements.

You also need a function in the pooler to fetch an ready element. If you go with the available bool method then you need to traverse the array looking if an entry with available = true, then you grab it’s reference set the available to false and call it’s activation function

awesome, thank you for sharing that link and your knowledge! I really appreciate it! Hopefully I’ll be able to figure out pools. It seems like it’ll be one of the more complicated things, but we all need to push ourselves and grow eventually. Now seems like a good time for me.

Thank you once again for all your help!