Pool and Pool with components.
by Matthew Hoesterey · in Torque X 2D · 09/15/2010 (7:34 pm) · 11 replies
I have a question about how pool and pool with components effects game logic.
One of the last bugs in my game (that I know about) is that sometimes when 4 characters are on the screen at once and all are shooting fireballs, if one fireball dies at the same time that another is spawned sometimes the one that is spawned will have some of the information from the one that died.
I pass information with the fireballs by creating a copy of a class called hitStatistics in one of my components. It seams that hitStatistics.Projectile will sometimes have the wrong projectile passed. The strange thing is I set hitStatistics to null when a projectile dies and have confermed that on creating the projectile actually does get passed the right info.
I did find that turning off pool fixes the problem. Does pool stop components from unregestering or cause them to be recreated with old property values (not the ones I set at register time)?
One of the last bugs in my game (that I know about) is that sometimes when 4 characters are on the screen at once and all are shooting fireballs, if one fireball dies at the same time that another is spawned sometimes the one that is spawned will have some of the information from the one that died.
I pass information with the fireballs by creating a copy of a class called hitStatistics in one of my components. It seams that hitStatistics.Projectile will sometimes have the wrong projectile passed. The strange thing is I set hitStatistics to null when a projectile dies and have confermed that on creating the projectile actually does get passed the right info.
I did find that turning off pool fixes the problem. Does pool stop components from unregestering or cause them to be recreated with old property values (not the ones I set at register time)?
#2
09/15/2010 (8:01 pm)
If you are using pooled objects, you are going to want to inherit from the GarageGames.Torque.Util.ObjectPooler.IResetable interface. The interface defines a Reset() function. Inside that function you will want to reset your object back to a base state. If you don't do that, it will keep the values of your old object when it gets "recreated".
#3
That is good to know John I think that might be whats messing things up. On recreation I think the fireballs are killing themselves cuz they their attack box is colliding with its own hit box due to leftover values. Thanks!
09/15/2010 (8:25 pm)
Thanks Ron and John. :)That is good to know John I think that might be whats messing things up. On recreation I think the fireballs are killing themselves cuz they their attack box is colliding with its own hit box due to leftover values. Thanks!
#4
Pooled objects and components are first unregistered and then Reset is called. If objects or components are not pooled then Dispose() is called instead.
09/15/2010 (9:04 pm)
TorqueBase already extends IResetable so that part is covered. You just need to override the Reset() method.Pooled objects and components are first unregistered and then Reset is called. If objects or components are not pooled then Dispose() is called instead.
#5
09/15/2010 (10:36 pm)
Thanks Duncan. I'm surprised resetting the values in Unregister isn't working. Perhaps the components don't get unregistered all the time or something. I'll try with the reset method.
#6
09/15/2010 (10:46 pm)
yeah they really should be resetting if you do it in unregister. best double check what's happening.
#7
I think this is whats happening and I'm not 100% but pretty sure as I confermed this by naming the projectiles when they are created.
So my projectiles are actually 3 objects. A parent object that moves and stores data. A hitbox object that lets the projectile get hit and a Attack-checker that hits other players hit boxes.
Whats happening I believe is that say Player 2s projectile hits something and is set to MarkforDelete.
Then at the same time player 1 projectile is created from the pooled object.
A component manually sets the position for the Attack check and Hit check pieces each frame (at the time I made this Mount to object was broke). I think when the projectile object is pooled the new player 1 projectile created is equal to the player 2 projectile so the hit box and checker objects move to the player 1 projectile destroying it.
I think the race condition is caused because of the delay in MarkforDelete and the ticks of the child set position component. The "child" objects don't know there parent has died yet.
I think changing the system to use mounting will fix the problem. I can also use a name on the projectile or set a flag on the child objects so they know the parent object is dead. Sadly I can't just nuke them as this causes another race condition with the Collsion system.
I'll let yous know how it goes.
09/16/2010 (1:40 am)
I think I've figured this out.I think this is whats happening and I'm not 100% but pretty sure as I confermed this by naming the projectiles when they are created.
So my projectiles are actually 3 objects. A parent object that moves and stores data. A hitbox object that lets the projectile get hit and a Attack-checker that hits other players hit boxes.
Whats happening I believe is that say Player 2s projectile hits something and is set to MarkforDelete.
Then at the same time player 1 projectile is created from the pooled object.
A component manually sets the position for the Attack check and Hit check pieces each frame (at the time I made this Mount to object was broke). I think when the projectile object is pooled the new player 1 projectile created is equal to the player 2 projectile so the hit box and checker objects move to the player 1 projectile destroying it.
I think the race condition is caused because of the delay in MarkforDelete and the ticks of the child set position component. The "child" objects don't know there parent has died yet.
I think changing the system to use mounting will fix the problem. I can also use a name on the projectile or set a flag on the child objects so they know the parent object is dead. Sadly I can't just nuke them as this causes another race condition with the Collsion system.
I'll let yous know how it goes.
#8
Use unregister when you want something to be gone *right away* and use markfordelete if you just want to mark it for deletion a bit later (e.g. you still have stuff in the current tick that might rely on the object existing, but you do want it to be deleted once that stuff is done)
09/16/2010 (10:41 am)
Sounds like you need to be calling Unregister directly instead of using MarkForDelete.Use unregister when you want something to be gone *right away* and use markfordelete if you just want to mark it for deletion a bit later (e.g. you still have stuff in the current tick that might rely on the object existing, but you do want it to be deleted once that stuff is done)
#9
Thanks!
09/16/2010 (12:40 pm)
Ah, So calling un-register will nuke the object. Should I also Mark it for delete to insure its removed from memory or does Unregister do that?Thanks!
#10
09/16/2010 (1:21 pm)
markfordelete just says to unregister at the next opportunity the engine gets. So no need to mark it for deletion as it will already be unregistered.
#11
09/17/2010 (7:11 pm)
Sweet thanks for the info. :)
Torque Owner Ron Barbosa
Disposable Fun
Should be easy enough to tell though...run it through the debugger, and add a breakpoint in the unregister method to see if you ever reach the breakpoint.
Also...check for iterations. If you have 5 fireballs, you should see unregister get called 5 times when they are destroyed. If it only gets called twice, then it's possible that some objects in the pool have been unregistered, but others remain.
This could create funky behavior.
Hope that helps...
--RB