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.
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.
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…
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?
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…
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 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)?
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?
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.