I have a table of game objects that I would like to delete after a slight delay due to an animation. The objects are stored in a table. After the deletion is triggered (i.e. the animation starts) the table is emptied. If new objects are spawned (and added to the same table) before the animation finishes, then the old objects are not deleted on animation completion. But if I wait and let the animation finish, the objects are deleted okay.
Code below:
local num = #self.line_parts
for i=1,num do
go.animate(self.line_parts[i], "scale", go.PLAYBACK_ONCE_FORWARD, 0.01, go.EASING_INBACK, 0.25, 0, function(self, url, property)
go.delete(url)
end)
end
self.line_parts = {}
Why doesn’t this work? Seems to be some sort of issue with referencing because adding more objects to the table appears to be the issue. But the table is emptied (reset even) regardless and it works so long as new objects aren’t added.
I know that animations of the same property interrupt the previous animation, which would cancel the callback. Indeed, the new objects have a scale animation applied on init. If I remove the scale animation then the callback fires and the old objects are deleted as intended.
Thanks for the answer, though unfortunately I remain confused! What does delay deleted mean and how does it cause the issue I’m observing?
The animation callback fires if I use a dummy animation, so it seems that newly spawned go’s overwrite the animation of old ones that are no longer referenced.
My answer was to this statement.
The game object will not be deleted immediately.
The game object is tagged as deleted, and will be removed at the end of the frame.
During this period, if any new game objects are created, they will have new ids (as the “old” ones are still taken).
I think your case is probably best explained with a small minimal repro case that we can test out.
I recreated the situation except the issue did not occur. So I started adding more and more to the minimal repro to figure out what the difference was.
What I haven’t mentioned but is very relevant is that when I spawn an object, I animate in the scale from near 0. As a callback to this scale animation finishing, I then trigger a looping scale animation (for juice).
So the life cycle of an object is:
Spawn function is triggered
Object is created via factory and scale set to ~0, reference stored in table
Animation to scale 1 is triggered, with a callback to 4)
Initial animation in 3) is completed, so looping scale animation triggered
Object exists for some time
Delete function is triggered
Animation to scale ~0 is triggered, with a callback to 9)
Table of object references reset
Game object deleted
Something seems to happen if I trigger a deletion before the spawning animations are completed.
I was close to having a theory but I failed to produce an even simpler repro. I’m attaching what I have here. My brain is now mush so I’m unable to do any more thinking for the moment.
My workaround is fine, so my interest is purely academical at this point. Hoping to nerd snipe somebody with this repro.
I took a quick look and my head started hurting from making sense of it
I believe the main problem is that you use go.animate(some_id, “scale”, …) in two (three actually) places and you run important code in the callbacks. If you start an animation on a property which is already animated it will be canceled and the callback will not be run.
Well…I guess I got “nerd sniped”, haha. I played with this for a while and I think I figured it out. Basically it’s what britzl said.
Whichever animation is started -last- overrides and cancels any earlier animations(on the same property of the same object).
But the sneaky part is that the delays are figured separately. So it’s whichever animation starts animating last.
For example: if you delay an animation for 1 second, at the end of that second that animation will kick in and destroy any other animations that are currently running.
Another interesting caveat: If you start them both at the same time then they’ll both run.
Brilliant! Thanks for taking the time to look at this.
I think that solves the issue I was having.
One thing though, I would like to use a timer but I’m confused about how to pass in a reference to the object I want to delete. The dummy animation looks like this:
Even though I wipe self.line_parts right after this, it still works because the animation callback gives me a reference to the url. How do I achieve the same for a timer?
Ah, true, you don’t get those extra paremeters to the callback. I see two solutions:
Anonymous functions: You’re already creating a new anonymous function for each callback, so you can use any variables you want when you create the function.
local local_url = msg.url("other object")
timer.delay(1, false, function()
go.delete(local_url)
end)
local objs_to_delete = {}
local function delete_object(self, handle, time_elapsed)
local obj = objs_to_delete[handle]
if obj then
go.delete(obj)
end
end
function init(self)
local local_url = msg.url("other object")
local timer_handle = timer.delay(1, false, delete_object)
objs_to_delete[timer_handle] = local_url
end