Optimizing Game?

Topics: Developer Forum
Nov 14, 2011 at 6:02 AM

Hey guys, I've been coding a game for a few months and we ended up implementing Farseer into the game a while back. It's been really awesome for all of the 2d stuff that we need to do, however we're now running into performance issues now that we've got a lot of stuff going on.

What we're doing is pretty much this (Same functionality as this game):

The game runs fine when you're flying around a ship and bouncing off of static objects. But when we start getting a lot of bullets on the screen, it gets mega laggy. The SolveIsland (Or whatever it's called) in the CLR shows 95% utilization of the game when we have about 600 bullets on screen. I'm not sure if that's normal or not, but it's been frustrating trying to debug. I've been working on it for weeks now with minimal success. I've toggled the isBullet flag, I've manually told stuff to sleep or be awake. Sleeping is allowed. I'm disabling bodies that aren't in use. We've got an object pooling for bodies. I've used Body.Deepclone(). Got a lot to think about!

What's come to mind recently is multithreading. That seems like the key, because when the physics engine gets laggy it's in the same thread as the drawing and player input. So if we can draw at 60fps while the physics runs at 10, I don't think the player would mind as much. The thing that really is unnerving is not being able to close the application while the game is crunching away. :P

I'm hoping that I'm making a newbie mistake and that somebody can direct me to a thread that makes me go 'doh!' but I haven't found anything like that on google. There are not many threads that are applicable that I can find.

Nov 14, 2011 at 1:26 PM

Are the bullets polygons?

Nov 14, 2011 at 10:33 PM
Genbox wrote:

Are the bullets polygons?

We draw the bullets with spritebatch. And we just draw a texture. For creating a bullet, I've just been using the BodyFactory.CreateRectangle() method for building new bullets. I build a stack of bodies and pop/push them when I need to.

Nov 15, 2011 at 7:37 AM

Got some more optimization in with the walls. Up'd the amount of bullets that I can have to about 1400 now, which is a hell of a lot better! Do you happen to know anything about threading?

I can paste you the class if you'd like for all the bullet stuff. It's about ~440 lines I'd say (including the comments).

Nov 15, 2011 at 1:16 PM

change rectangle to circle because it creates less contacts and should be faster with SAT

Nov 17, 2011 at 12:04 AM

I think that I've optimized it for the most part. It's still not as fast as I'd like it to be, but I don't think that I can do anything to make it any better. I'll just need to make it a goal for the future to rewrite the physics engine or something. I don't know if anybody here has any experience with large amounts of small bodies. I'll have to post up a screenshot later, might make it easier to simplify what I'm trying to talk about.

The only think that I'm thinking might have an effect is when bullets travel over other bullets it starts to lag more. Maybe it's going through the OnCollision step even though they're set to ignore each other? We're using CollisionCategories. Is that better or worse than CollisionGroups?

One thing I'm curious about is, how do you guys draw your bodies as to not lag? We're currently going through a for loop for every bullet. And if the bullet is marked as active, it draws. It's a preallocated stack of bodies for the bullets. I think I've got the ObjectPooling down for the most part. I assume that's faster than building and destroying bodies rapidly.


Nov 19, 2011 at 5:21 PM

Do you really need the bullets to be real Farseer physics objects?

When I used Farseer in my game a while ago (Farseer 2.1) I used the function Collide located in PhysicsSimulator.cs, I guess there is something similar in Farseer 3.3. This function would take a Vector2 and check if there was any physics object at that position.

If you think this works in your game you should also look into the Collide function and possible change this to only do the AABB.Contains check. Might be enough for bullets.

Nov 20, 2011 at 4:04 AM

Oh man! Thanks Panzer, I'm going to try that out. We previously wrote a collision engine for our game, but we had a hard problem trying to get mirroring of bullets to work. Like when you fire a bullet, it bounces off the wall. Determining that angle was the only thing we needed to figure out. Though I may be able to avoid that now... :D

One thing that came to mind was setting the OnBroadphaseCollision event to be on the wall instead of the bullet. That may help decrease lag. I'm going to try that and see where it gets me, but I think the long term solution will be to implement something like you were talking about. The only thing that I'm going to have to figure out is how to make the client move objects based on time (World.Step(Game.Time.Millseconds *0.001)) instead of based on iteration (Position.X = Position.X + Speed.X). That shouldn't be TOO hard though.

I didn't know about AABB prior to using this engine. It seems very efficient.

Nov 20, 2011 at 2:40 PM

Yes that should not be a problem, I had a Update bullets function that would take a "float elapsed" and in this function I would just do

bullets[i].Pos.X += bullets[i].Velocity.X * elapsed;
bullets[i].Pos.Y += bullets[i].Velocity.Y * elapsed;

And elapsed is:
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

Also if you do it this way you can have the bullets array static and when spawning a new bullet you keep track of the next free one

bullets[nextbullet].alive = true;

so adding new bullets take no time