removing physics bodies

I get a memory leak when trying to remove objects. I’ve determined that it happens only when each of the objects are given physics bodies, which I thought I was removing correctly according to the documentation. My code:

[code]
local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 25

local background = display.newImage(“background.png”)

scoreTextfield = display.newText( " " … score, 280, 105, nil, 14 )
scoreTextfield:setTextColor( 0, 0, 0, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newImage( “bar.png” )
bar.x = 170 ; bar.y = 350
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function randomBall ()

if x < 3000 then

local imageBall = display.newImage( “ball.png” )

local randomPos = math.random

imageBall.x = 10 + randomPos( 300 ); imageBall.y = -20

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local function onLocalCollision( self, event )

if ( imageBall.x ) then

if ( imageBall.y > 300 ) then

imageBall:removeEventListener( “collision”, imageBall )
imageBall:removeSelf()
imageBall = nil

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

end

end

imageBall.collision = onLocalCollision

end

end

y = 30

local timberBall = timer.performWithDelay( x, randomBall, y )

[/code] [import]uid: 10903 topic_id: 3988 reply_id: 303988[/import]

That removeSelf doesn’t happen immediately as far as I know , its a function that tells the system the physical part of the
item needs removing at a safe point - safe point being outside box2d’s physics calculation step, before the next enterframe most likely. Therefore enterframe event is presumably also the best time to be printing out your system memory. Does that make any difference? [import]uid: 6645 topic_id: 3988 reply_id: 12057[/import]

If I drop the nil out that seems to save a little memory, but it still leaks. Here’s the code modified to reflect that change, and also doesn’t require images so it can be dropped into the simulator.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 100

scoreTextfield = display.newText( " " … score, 280, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function randomBall ()

if x < 3000 then

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

local function onLocalCollision( self, event )

if ( imageBall.x ) then

if ( imageBall.y > 300 ) then

imageBall:removeEventListener( “collision”, imageBall )
imageBall:removeSelf()

end

end

end

imageBall.collision = onLocalCollision

end

end

y = 4

local timberBall = timer.performWithDelay( x, randomBall, y )
[/code] [import]uid: 10903 topic_id: 3988 reply_id: 12060[/import]

i’m not sure but at a guess, the imageBall inside your collision function doesn’t always refer to the actual imageBall calling that collision. best way to check this is test if imageBall==self inside your collision. maybe I’m wrong

personally i would use

[lua]local function onLocalCollision( obj, event )
…if(obj.x…)

obj:removeSelf()
etc[/lua]

rather than refer to a variable (imageBall) that is outside of the collision function scope
also like i said, print out your memory in your enterframe function. The memory isn’t going to get cleared straight away when you call :removeSelf() since Corona needs to keep a reference to the Box2D object until it is safe to remove it from the Box2D world (outside of the physics .step() and therefore most likely just before the next enterFrame call) [import]uid: 6645 topic_id: 3988 reply_id: 12129[/import]

Are you suggesting to add an enterframe function or to use one instead of the collision function? I put a check memory function on a timer that occurs well after the objects disappear. I still get a memory leak checking it that way.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 50

scoreTextfield = display.newText( " " … score, 200, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function randomBall ()

if x < 3000 then

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then

obj:removeSelf()

end

end

end

imageBall.collision = onLocalCollision

end

end

y = 10

local timerBall = timer.performWithDelay( x, randomBall, y )

local function memCheck ()

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )

[/code] [import]uid: 10903 topic_id: 3988 reply_id: 12194[/import]

Code’s a lot better I think. But why add a separate collision function for every ball. Why not put the collision function outside of the randomball function and reuse it for all balls? [import]uid: 6645 topic_id: 3988 reply_id: 12200[/import]

When I move the collision function outside the randomBall function the collisions don’t register at all.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 50

scoreTextfield = display.newText( " " … score, 200, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function randomBall ()

if x < 3000 then

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

imageBall.collision = onLocalCollision

end

end

y = 10

local function memCheck ()

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then

obj:removeSelf()

end

end

end

local timerBall = timer.performWithDelay( x, randomBall, y )

[/code] [import]uid: 10903 topic_id: 3988 reply_id: 12202[/import]

As mentioned before you’re trying to call the collision function before you’ve defined it. Move it up [import]uid: 6645 topic_id: 3988 reply_id: 12203[/import]

Like this?

local physics = require("physics")  
physics.start()  
physics.setGravity( 0, 0 )  
   
local score = 0  
   
local x = 50  
   
scoreTextfield = display.newText( " " .. score, 200, 105, nil, 14 )  
scoreTextfield:setTextColor( 255, 255, 255, 255 )  
   
scoreTextfield.text = " " .. score  
   
collectgarbage("collect")  
score = "System Memory : " .. collectgarbage("count")  
scoreTextfield.text = " " .. score  
   
local bar = display.newRect( 0, 350, 350, 20 )  
bar:setFillColor ( 255, 255, 255 )  
physics.addBody( bar, "static", { density=2.9, friction=0.0, bounce = 0 } )  
  
local function onLocalCollision( obj, event )  
  
 if ( obj.x ) then   
  
 if ( obj.y \> 315) then   
  
 obj:removeSelf()  
  
 end  
  
 end  
  
end  
   
local function randomBall ()  
   
if x \< 3000 then  
  
 local randomPos = math.random  
  
 local imageBall = display.newRect( randomPos(300), -20, 30, 30 )  
 imageBall:setFillColor ( 255, 255, 255 )  
  
 physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )  
   
 imageBall:setLinearVelocity( 0, 600 )  
  
 imageBall:addEventListener( "collision", imageBall )  
   
 imageBall.collision = onLocalCollision   
   
end  
   
end  
   
y = 14  
   
local timerBall = timer.performWithDelay( x, randomBall, y )  
   
local function memCheck ()  
   
 collectgarbage("collect")  
 score = "System Memory : " .. collectgarbage("count")  
 scoreTextfield.text = " " .. score  
   
end  
   
local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )  

I still get a leak. [import]uid: 10903 topic_id: 3988 reply_id: 12212[/import]

Updated code, still leaking.

[code]
local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local x = 50

local randomPos = math.random

collectgarbage(“collect”)
print("System Memory : " … collectgarbage(“count”))

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then
obj:removeSelf()
obj=nil
print(“removed”)
end

end

end

local function randomBall ()

if x < 3000 then

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )

imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

imageBall.collision = onLocalCollision

end

end

y = 11

local timerBall = timer.performWithDelay( x, randomBall, y )

local function memCheck ()

collectgarbage(“collect”)
print("System Memory : " … collectgarbage(“count”))

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )
[/code] [import]uid: 10903 topic_id: 3988 reply_id: 12303[/import]

Here’s a simpler version developed by jmp909, who also thinks this might be a bug.

[code]

local physics=require(“physics”)
local rnd = math.random

physics.start()
physics.setGravity(0,0)

local function removeBall(obj)
obj:removeSelf()
end

local function addBall()

local ball = display.newCircle(rnd(200)+50, rnd(200)+50, rnd(50)+5)
ball:setFillColor(128,128,128)
physics.addBody(ball)
transition.to(ball, {time=400, alpha=0, onComplete=removeBall})

end

local function memCheck (event)

collectgarbage(“collect”)
print("System Memory : "…collectgarbage(“count”))
end

local timerBall = timer.performWithDelay(100, addBall, -1)
local timerCheck = timer.performWithDelay( 50, memCheck, -1 ) [import]uid: 10903 topic_id: 3988 reply_id: 12339[/import]

Just wanted to bump this, can any Ansca staff confirm or refute this as a bug? [import]uid: 10903 topic_id: 3988 reply_id: 12519[/import]

Got it. we will look into it.

c [import]uid: 24 topic_id: 3988 reply_id: 12902[/import]

Got it. we will look into it.

c [import]uid: 24 topic_id: 3988 reply_id: 12903[/import]

Thank you, I have been having a very similar problem. In my case the physics bodies are being attached to animated sprites so I thought that was the problem but couldn’t find any info about it.

I hope this is the same problem I am having because at least i know now it is being looked at. [import]uid: 9187 topic_id: 3988 reply_id: 12990[/import]

Yes, I repro’d the issue and filed an internal bug (2153) for an engineer to investigate. I’ll let you know of any updates or workarounds.

Tim [import]uid: 8196 topic_id: 3988 reply_id: 13401[/import]

I’d like to hear back about it as well. It’s a pretty major issue if your going to be creating multiple physics bodies. Games archetypes like tetris, doodle jump, the event would all be impossible to make. [import]uid: 10903 topic_id: 3988 reply_id: 19685[/import]

Is this issue solved? I’m having the same problem. I’ve got lots of random enemies spawning with a new physics body each. On collision it’s removed. I get a huge fps loss after I’ve played a while [import]uid: 30185 topic_id: 3988 reply_id: 19682[/import]

I would like to find out about this as well. I shelved my previous project due to physics issues. It would great to know that physics are working properly now. [import]uid: 9187 topic_id: 3988 reply_id: 19872[/import]

Same here, this is a major problem in my current game… [import]uid: 26547 topic_id: 3988 reply_id: 20126[/import]