Wednesday, June 16, 2010

Stress testing and optimizing

So we're at the point where I need to start making sure everything runs as smooth as it can for Space Swine. I've been going through some slow points in the code to speed them up. I'll run through a few things that I learned NOT to do while making the game. Now I'm no expert by any stretch so some of these may seem obvious but it's what I learned along the way and maybe it'll help someone else out.



  • Creating textures/sounds on-the-fly. Every wave I'm creating up to 30 or so new enemies and every time an enemy was created it was loading a texture and a death sound for that particular enemy. When this all happens on one frame you get some pretty big lag spikes which are no good. I ended up preloading everything which eliminated the lag spikes when I was creating enemies. Instead of multiple instances of a single texture, which never change, there's now just a single one always available. To further improve the performance, I could create a set amount of a certain enemy before the game even starts, and 'reuse' enemies that are currently inactive. More on this in a later bullet point.
  • Updating strings every frame is also bad. In between waves, when absolutely nothing was going on I have some text popup on the screen that counts down to the next wave, shows the wave number, and on every 10th wave shows the current health/damage multiplier. For the countdown timer it just counts down from 3, using Math.Ceiling(...) so it goes 3...,2...,1... and then the wave begins. Maybe it was the math being called 60 times a second that was slowing it down, I didn't check. Anyways I fixed it by making a new method called UpdateHUD(...) and I set it on a timer (Nick Gravelyn's Timer/Interpolator code) so it only calls it once per second. Instead of calling it 60 times a seconds, which is overkill, it only calls it once a second which greatly helped out. I also attached the same concept to the player's HUD so it only updates once a second. The player HUD has a lot more elements being updated so that slowdown was even bigger until I changed it.
  • Be wary of particles. Nearly every game has them nowadays and if you don't keep a close hold on them it can get out of control. I'm using the Project Mercury Particles source code for my particles and it's pretty awesome because it comes with an editor. I never had any problems with it until at one point in my game there were up to 20 rockets on the screen, each with a little fire trail behind it. I'm not really sure on the number, but I think I was allowing them to create 32 particles a frame, with a max of 1000 total. I used the same particle set for all rockets, so they had to split 1000 particles between each other. That 1000 particle limit was getting hit almost instantly when the particles started showing up and I was getting pretty big spikes because of it. I ended up lowering the quantity of particles they were allowed to create per frame from 32 to 6 or so. And the big kicker is that it looks nearly identical to how it did before, and now there's no slowdown.


Now for a few things that worked out very well. As I mentioned in the first bullet point, creating a bunch of something at the very beginning, then using a variable to set them active/inactive when you need them works very well.

  • First off, you're not creating new objects, along with everything inside of that object, you're just setting them inactive as soon as they die. Instead of creating an all new one when you need it, you just set an inactive one to active. I used this concept for all of the bullets for players/enemies. Each player can have up to 100 bullets active at any time, and you can have up to 4 players. That's 400 bullet objects on the screen at any time just for the players. The enemies, while they vary per type, can have up to 16 I believe and most bosses have up to 50. But as I mentioned above you can have up to 30 enemies on the screen at any time so that all adds up to maybe 700/800 bullets on the screen at once. To ever hit a situation like that would be very rare, but it's totally possible so I had to plan for it.
I'm currently working on one slowdown that I haven't figured out a solution to yet and it has to deal with my scoring system. I have it so every time a bullet hits an enemy you get 12 points. That way when playing multiplayer the person hitting more enemies will have the better score which I think seems fair. Adding the score is inside of a for loop which runs through all of my bullets, then all of the enemies, to check for a collision. So basically if a bullet collides with an enemy you get 12 points then the bullet gets set to inactive until needed again. Just a single line of code is causing a FPS drop from 60FPS to about 45 with 4 players constantly shooting. Here's the culprit on my todo list. I'm thinking it has something to do with being called every frame AND inside of a double for loop checking every bullet/enemy for a collision. Weird that such a simple line can have a dramatic performance decrease!

score += scorePerHit;

2 comments:

  1. Hey Matey,

    One easy way for speeding up the multi-loop issue you have is to offset the amount done to multiple frames. For example, do only player 1s bullet collision on odd frames, and player 2s on even frames. This will then doble your performance on that very easily. This kind of thing can be an issue though, depending on size of bullets and speed and size of enemies etc. (sometimes they can get through an enemy).

    good luck, sounds great,
    Da Voodoochief

    ReplyDelete
  2. Sorry I missed the comment but that sounds like an awesome idea. I don't think my bullets are moving too fast to pass through an enemy in the time of a single frame but I'll have to test to make sure, thanks. :)

    ReplyDelete