How to remove an item after a transition.to is called

So I am making a game where coins fall from the sky and when they land they are supposed to wait for awhile and then fade and then they are supposed to be removed.

This is how I thought you might be able to do it:

local function coindestroy(event)     if(event.phase == "ended" and alive == true) then         local i = event.target.id         transition.to( coin[i], { time=1000, delay = 500, alpha = 0.01, onComplete=function()             coin[i]:removeSelf() --This is line 62 and where the error comes from             coin[i] = nil         end})     end end

However, that gives me an error right after the coin fades. It says, “attempt to index field “?”(a nil value)”

Its because I am trying to remove the coin that is being transitioned, right? How would one correctly do this?

You can do the following:

local function removeCoin(obj) obj:removeSelf() end transition.to( coin[i], { time=1000, delay = 500, alpha = 0, onComplete=removeCoin})

The reason is ; when you create your transition.to(), the onComplete = function() creates a closure - this is like a ‘local snapshot’ of the local variables at the time. So in your onComplete function, the value of i will be correct.

The problem is coin - coin is a reference to a table, and this is preserved (or if it is a global, it is the same), not the value of coin[i] - it saves a reference to a table, not the real thing.

So what your code is actually doing is setting coin[i] to nil, and then trying to removeSelf() that coin[i] a bit later on, which is what your error message means - this means you are doing someTable:someMethod() or someTable.someValue where someTable is actually nil.

Renato’s solution will work fine. onComplete also has a single parameter, the object , which is coin[i] in your case , so you could just change it to :

transition.to(coin[i], \<stuff\>, onComplete = function(obj) obj:removeSelf() end) coin[i] = nil

(this is the same as Renato’s just without the extra function)

Sadly, both of these answers give me the error: “attempt to call method ‘removeSelf’ (a nil value)”

can you show your code after modification? that error line probably wants to tell you that it didn’t find any object that should be removed. The options are whether you didn’t give the right parameter object, or the object itself is not exist

Here is where I create the coin:

local function createcoins() &nbsp;&nbsp; &nbsp;if(alive == true and paused == false) then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;local i = coinnumber &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i] = display.newImage("img/coin.png") &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].x = math.random(0, 960) + coin[i].contentWidth/2 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].y = 0 - coin[i].contentHeight \* 2 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;physics.addBody(coin[i], "dynamic", {friction=1, bounce = 0.2, radius=15, density = 0.001, filter = ballfilter}) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].id=i &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].group = "coin" &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i]:addEventListener("collision", coindestroy) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i]:setLinearVelocity( 0, 300 ) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coinnumber = coinnumber + 1 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].linearDamping = 1 &nbsp;&nbsp; &nbsp;end end

Here is my timer in the enterScene:

timers[4] = timer.performWithDelay(math.random(2222, 4444), createcoins, -1)

Here is where I destroy the coins:

local function coindestroy(event) &nbsp;&nbsp; &nbsp;if(event.phase == "ended" and alive == true) then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;local i = event.target.id &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;transition.to( coin[i], { time=1000, delay = 500, alpha = 0.01, onComplete = function(obj) obj:removeSelf() end}) &nbsp;&nbsp; &nbsp;end end

you might want to check the id of the coin. I am assuming that you give the id from a variable called coinnumber. Is it a table, or just 1 variable?

try printing out the id every time you want to create and destroy the coin. does it gives the same id? are you creating a loop of id’s from a loop? Usually, i will create an id based on a loop, and give the id on each loop, so they have a consecutive number id.

Okay, I figured out what was wrong with my code. Every time the coin would bounce on the ground it would call the transition, so it would try to be removed multiple times.

You can do the following:

local function removeCoin(obj) obj:removeSelf() end transition.to( coin[i], { time=1000, delay = 500, alpha = 0, onComplete=removeCoin})

The reason is ; when you create your transition.to(), the onComplete = function() creates a closure - this is like a ‘local snapshot’ of the local variables at the time. So in your onComplete function, the value of i will be correct.

The problem is coin - coin is a reference to a table, and this is preserved (or if it is a global, it is the same), not the value of coin[i] - it saves a reference to a table, not the real thing.

So what your code is actually doing is setting coin[i] to nil, and then trying to removeSelf() that coin[i] a bit later on, which is what your error message means - this means you are doing someTable:someMethod() or someTable.someValue where someTable is actually nil.

Renato’s solution will work fine. onComplete also has a single parameter, the object , which is coin[i] in your case , so you could just change it to :

transition.to(coin[i], \<stuff\>, onComplete = function(obj) obj:removeSelf() end) coin[i] = nil

(this is the same as Renato’s just without the extra function)

Sadly, both of these answers give me the error: “attempt to call method ‘removeSelf’ (a nil value)”

can you show your code after modification? that error line probably wants to tell you that it didn’t find any object that should be removed. The options are whether you didn’t give the right parameter object, or the object itself is not exist

Here is where I create the coin:

local function createcoins() &nbsp;&nbsp; &nbsp;if(alive == true and paused == false) then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;local i = coinnumber &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i] = display.newImage("img/coin.png") &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].x = math.random(0, 960) + coin[i].contentWidth/2 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].y = 0 - coin[i].contentHeight \* 2 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;physics.addBody(coin[i], "dynamic", {friction=1, bounce = 0.2, radius=15, density = 0.001, filter = ballfilter}) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].id=i &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].group = "coin" &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i]:addEventListener("collision", coindestroy) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i]:setLinearVelocity( 0, 300 ) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coinnumber = coinnumber + 1 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;coin[i].linearDamping = 1 &nbsp;&nbsp; &nbsp;end end

Here is my timer in the enterScene:

timers[4] = timer.performWithDelay(math.random(2222, 4444), createcoins, -1)

Here is where I destroy the coins:

local function coindestroy(event) &nbsp;&nbsp; &nbsp;if(event.phase == "ended" and alive == true) then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;local i = event.target.id &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;transition.to( coin[i], { time=1000, delay = 500, alpha = 0.01, onComplete = function(obj) obj:removeSelf() end}) &nbsp;&nbsp; &nbsp;end end

you might want to check the id of the coin. I am assuming that you give the id from a variable called coinnumber. Is it a table, or just 1 variable?

try printing out the id every time you want to create and destroy the coin. does it gives the same id? are you creating a loop of id’s from a loop? Usually, i will create an id based on a loop, and give the id on each loop, so they have a consecutive number id.

Okay, I figured out what was wrong with my code. Every time the coin would bounce on the ground it would call the transition, so it would try to be removed multiple times.