Performance issues with "gibs" system

Topics: Developer Forum
Apr 11, 2010 at 9:01 PM

hello all

 

i've got some performance problem on farseer with my gib system :

in my scene there is about 30 physics body and geom who are set to static ( it's just the collision boxes of my level ).

Then i have four players, each have a body and a geom, but of course they are not static.

I try to make a gib system, when a player kill another player i create 4-6 small Circles Geom and body, and after 2 seconds i disable physic on them by destroying the geom and the body, so the physic simulator doesn't have to update them for too long.

The problem is when 2 or 3 player are killed and some gibs are spawned at the same time there is a very big slowdown ( on xbox it's almost a slideshow ) during some seconds.

I tried to set the BroadPhaseCollider but i've got almost the same result with the 3 algorythm.

I think i'm doing something wrong, but i wander what ( I use Farseer physics 2.1.3 ).

Apr 11, 2010 at 11:02 PM

hey,

If you could possibly put some code samples on here, that'd be great.

It may help if you make your circles in advance, and just toss them off

screen disabled while you're not using them.

I doubt it's garbage collection that's causing the problem, but possibly

something related.

 

-Oranjoose

Apr 11, 2010 at 11:49 PM

here is my gibs class, i simply spawn some element from the player class when the player get killed, i store every gibs element in a list ( peraphs i should use Farseer Pool )
when the list raise the maximum ( about 20 elements ), the first elements are destroyed.

But has you can see the body and the geom is destroyed at the end of the gibs lifetime( 2 second max in fact ).

thanks for your help :


public class Gibs { private Body m_GibBody; private Geom m_GibGeom; private Texture2D m_GibTexture; private GameState m_GameInstance; private int m_xRadius; private int m_yRadius; private Vector2 m_Position; private float m_Rotation; private bool m_bIdleFlag; private float m_lifeTime; private float m_life; private const float GIBS_MASS = 1F; private const float GIBS_INERTIA = 0.5F; private const float GIBS_FRICTION = 1F; public Gibs( GameState game,Vector2 Position, float Life, ref Texture2D GibTexture ) { Random rand = new Random(); m_GameInstance = game; m_xRadius = 5; m_yRadius = 5; m_bIdleFlag = false; m_GibBody = BodyFactory.Instance.CreateCircleBody(m_GameInstance.m_PhysicManager, m_xRadius, GIBS_MASS); m_GibGeom = GeomFactory.Instance.CreateCircleGeom(m_GameInstance.m_PhysicManager, m_GibBody, m_xRadius,10); m_GibTexture = GibTexture; m_GibGeom.CollisionCategories = COLLISIONS_CATEGORIE.GIBS; m_GibGeom.CollisionGroup = 1; m_GibGeom.CollidesWith = COLLISIONS_CATEGORIE.ALL & ~COLLISIONS_CATEGORIE.PLAYER & ~COLLISIONS_CATEGORIE.GIBS ; m_GibGeom.Tag = TAG.TAG_GIB; m_GibBody.Position = Position; m_Position = Position; m_Rotation = 0; m_GibBody.MomentOfInertia = GIBS_INERTIA; m_GibGeom.FrictionCoefficient = GIBS_FRICTION; m_life = Life; int speedx = rand.Next(-200, 200); int speedy = rand.Next(-200, 200); m_GibBody.ApplyImpulse( new Vector2( speedx, speedy ) ); } public void Destroy() { m_GibTexture.Dispose(); } public void DestroyBody() { m_GibBody.Dispose(); m_GibGeom.Dispose(); } public void Update( float elapsed ) { if (!m_bIdleFlag) { if (m_lifeTime > m_life) { m_bIdleFlag = true; DestroyBody(); } else { m_Position = m_GibBody.Position; m_Rotation = m_GibGeom.Rotation; } m_lifeTime += elapsed; } } public bool IsElapsed() { return m_bIdleFlag; } public void Draw() { Rectangle rect = new Rectangle(0, 0, m_xRadius*2, m_yRadius*2); m_GameInstance.spriteBatch.Draw(m_GibTexture, m_Position, rect, Color.White, m_Rotation , new Vector2(m_xRadius , m_yRadius ), 1F, SpriteEffects.None, 1); } }

Apr 12, 2010 at 1:12 AM

I don't see anything in there that should significantly slow anything down.

The only thing I can think of is that if too many of these are created in a single frame,

it forces the Garbage Collector to do a pass, and that can cause a slowdown in performance

all at once.

Each MB that is allocated forces the Garbage Collector to run.

I would recommend loading these instances at load time, and store them in a list beforehand,

so that all you have to do is call applyimpulse when you need them, and put

them on the screen enabled

 

Apr 12, 2010 at 1:18 PM
Edited Apr 12, 2010 at 1:23 PM

Due to garbage collection, you should really avoid doing any allocations whilst the game is running (this is ESSENTIAL for a smooth game on Xbox).

It's not clear from the code you posted what happens when the gibs are spawned - do you create a "new Gibs(...)"?

If so, you shouldn't. Instead, try using the Farseer pool and pre-create the maximum number of Gibs you'd expect to see at any time.

Then, to spawn a gib you fetch one from the pool and initialise it (ie set it's position and add body and geom to physics engine).

When the gib dies, insert it back into the pool and remove it from the physics engine. Create*Body and Create*Body are generally a bad idea once gameplay has started.

[EDIT] oops! I just realised I was basically repeating what oranjoose said already :)

[EDIT2] Since you are passing the physicsManager to the CreateCircle*() methods, it is clear that you're creating them when you spawn them.... so I'd say memory allocations are almost certainly the issue here.

 

Apr 13, 2010 at 8:27 AM

thanks for your advise, has you say i change my code in order to stop making new object during gameplay. Has expected it  really improved the performance.

However i still have slowdow but i think it's because i wake up too many object at the same time.

Thanks for your help

Developer
Apr 13, 2010 at 12:33 PM

Try changing your frame rate to 60 fps or even 30.