Delete a reference to an object without deleting the object

If I have an object, say a physics body or class, and I have stored the reference to the object in two variables a and b. Can i delete a without deleting the object ?(as the reference is still stored in b)

I would say yes.

Thanks @Dave1707, I think that’s the 3rd of my questions that you’ve answered today

@Coder I tried some code and what I found out was, you can set a=nil and b will still work. But if you do a:destroy(), then b doesn’t work.

@dave1707, @Coder - as long as there is a reference, an object will not be deleted.

When the last reference is removed, the object will be deleted at the next garbage collection, which is generally within the next minute. This delay doesn’t matter for most objects because they are just blocks of memory, but it can matter for physics objects, because you want them to disappear straight away when you delete references and stop drawing images for them, rather than sticking around and invisibly getting in the way of other objects.

This delay can also cause confusion when you define physics objects without assigning them to a global variable, eg creating walls around the screen in setup. They will work fine initially, but they will disappear within a minute when the garbage gets collected.

Coming back to the problem of physics objects not being deleted as soon as all references are gone, the destroy command is provided to delete the physics object straight away - and it doesn’t care whether there are any references to the object.

Note - always destroy the physics object before deleting the reference. If you do it the other way round, there is no way to destroy the object because there is no way to reference it.

@Ignatz Try this example. I create an object “a” and set “b” equal to it. In the touched function I set “a” equal to nil when you tap the screen. The “b” object remains and continues on it’s way. Then uncomment the “a:destroy()” line in the function touched and run the code again. Once “a” is destroyed, so is “b”. So your first statement “as long as there is a reference, an object will not be deleted” doesn’t seem to be true because “b” should still be referencing it.


function setup()
    a=physics.body(CIRCLE,20)
    a.x=WIDTH/2
    a.y=HEIGHT
    a.gravityScale=.2
    b=a     -- set "b" = to "a"
end

function draw()
    background(40, 40, 50)
    fill(255)
    text("tap screen",WIDTH/2,HEIGHT/2)
    if a~=nil and a.x~=nil then
        ellipse(a.x,a.y,40)
        fill(255,0,0)
        text("A",a.x,a.y)
    end
    fill(255)
    if b~=nil and b.x~=nil then
        ellipse(b.x+100,b.y,40)
        fill(255,0,0)
        text("B",b.x+100,b.y)
    end
end

function touched(t)
    if t.state==BEGAN then
        --a:destroy() -- this destroys a and b
        a=nil   -- this stops "a" but allows "b"
    end
end

One way around the above problem is to recreate “b” with the “a” values just before destroying “a”.

EDIT: I forgot the gravityScale, so I included it.


function setup()
    a=physics.body(CIRCLE,20)
    a.x=WIDTH/2
    a.y=HEIGHT
    a.gravityScale=.2
    b=a
end

function draw()
    background(40, 40, 50)
    fill(255)
    text("tap screen",WIDTH/2,HEIGHT/2)
    if a~=nil and a.x~=nil then
        ellipse(a.x,a.y,40)
        fill(255,0,0)
        text("A",a.x,a.y)
    end
    fill(255)
    if b~=nil and b.x~=nil then
        ellipse(b.x+100,b.y,40)
        fill(255,0,0)
        text("B",b.x+100,b.y)
    end
end

function touched(t)
    if t.state==BEGAN then
        b=physics.body(CIRCLE,20)
        b.x=a.x
        b.y=a.y
        b.linearVelocity=a.linearVelocity
        b.gravityScale=a.gravityScale
        a:destroy() -- this destroys a
        a=nil   -- this stops "a" but allows "b"
    end
end

@ dave1707 - perhaps I wasn’t clear.

  1. Destroy simply deletes a physics object. It doesn’t care about references.

  2. a and b refer to the same object, so destroying a also destroys b

So deleting a keeps the physics object alive via b, but destroying a also destroys b.

@Ignatz I wasn’t following exactly what you were saying at first. But I agree with what you just said. That also agrees with what I was seeing with my demos. But I haven’t been able to prove if setting “a” to nil gets rid of the actual physics object or is it still around to interact with other objects.

@Ignatz Here’s a demo showing that setting “a” to nil doesn’t get rid of it. It’s still around to interact with other objects. To get rid of it completely, it has to be destroyed. Run the demo with and without uncommenting a:destroy() in touched. So what this show is you can’t set b=a and destroy “a” without destroying “b”. If you don’t destroy “a”, then “a” is still around to get in the way of the other objects. The only way is to set b=a and just before destroying “a”, you have to recreate “b” and set it with the values of “a”.


function setup()
    e=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
    a=physics.body(CIRCLE,50)
    a.x=WIDTH/2
    a.y=HEIGHT-100
    a.gravityScale=.2
    b=physics.body(CIRCLE,50)
    b.x=WIDTH/2
    b.y=HEIGHT
    b.gravityScale=.2
end

function draw()
    background(40, 40, 50)
    fill(255)
    text("tap screen",WIDTH/2,HEIGHT/2)
    if a~=nil and a.x~=nil then
        ellipse(a.x,a.y,100)
        fill(255,0,0)
        text("A",a.x,a.y)
    end
    fill(255)
    if b~=nil and b.x~=nil then
        ellipse(b.x,b.y,100)
        fill(255,0,0)
        text("B",b.x,b.y)
    end
end

function touched(t)
    if t.state==BEGAN then
        --a:destroy() -- this destroys a and gets rid of it.
        a=nil   -- this removed a but doesnt get rid of it.
    end
end

@dave1707 - this code will show how the garbage collector destroys a physics object when there are no references. Run it and touch the screen to set a to nil, then wait and watch for the floor to disappear (and the ball to fall through) within the next minute or so. This shows that setting a to nil gets rid of the physics object - eventually.

function setup()
    a=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) 
    x=physics.body(CIRCLE,100)
    x.restitution=1
    x.x=WIDTH/2
    x.y=HEIGHT/2
end

function draw()
    background(220)
    fill(255,255,0)
    ellipse(x.x,x.y,200)
end

function touched(t)
    if t.state==ENDED then 
        a=nil
        print "Floor deleted, wait a minute or so"
    end
end

This demo, and your demo above simply confirm what I said earlier, that setting a to nil doesn’t get rid of the physics object immediately, it takes up to a minute to happen because it is done by garbage collection, which only happens infrequently so as not to hammer your performance.

So yes, it get rid of a physics object you should destroy it first. The sample code in the documentation of the destroy function makes this clear

-- destroy should be used before
-- setting a body to nil
circle = physics.body(CIRCLE, 100)
circle:destroy()
circle = nil

@Ignatz One thing that works is to add collectgarbage() right after a=nil. Then you don’t have to wait.