Need clarification about performance, enterFrame events and object reference

Hi everybody!

I’m having a performance iusse in my game. The game starts smooth but after a few minutes of playing it starts lagging, and it keeps doing it even if the game change the composer scene (i.e. game finished and started again). It’s clear that there’s something wrong in my code and I’m trying to find out what.

There are two thing I’m not sure about: the first is the use I’m making of the enterFrame event applied on a display object. Example:

local function create\_my\_object() local my\_object = display.newImageRect(...); --inizialize useful variables applied to my\_object function my\_object:enterFrame() --object behaviour... end function my\_object:finalize() Runtime:removeEventListener("enterFrame", myObject); end Runtime:addEventListener("enterFrame", my\_object); my\_object:addEventListener("finalize"); end 

If i call this function many times, to create different instances of this object, is it ok? Or I’m forgetting to clean up something after the object is removed?

Note that the object my_object can be removed in many different ways, inside and outside this function. For example it can be removed with a onComplete function inside a transition.to, or it can be removed by another function that detects collisions, or the game can just change the composer scene removing all objects linked to the display group.

The second question, more important, is about cleaning up variable reference to objects.

For example, if I call the function create_my_object from another function, the reference to the object my_object is a local variable inside the create_my_object function.

If the code that removes the object is inside the create_my_object function, I can write display.remove(my_object); my_object = nil;

But if the object is removed by another function, i.e. collision detection:

local function on\_collision(event) if (event.object1.myName == "enemy") and (event.object2.myName == "bullet") or (.....) then local what\_object; if (event.object1.myName == "enemy") then what\_object = event.object1; else what\_object = event.object2; end display.remove(what\_object); what\_object = nil; end end

In this case I cannot set to nil the original variable associated with the enemy object.

Should I write in every function that generates object a finalize function that sets to nil the local reference, or it is done automatically?

Hello,

I don’t clearly understand your questions.

In the create function, it will be usefull to return the object in case of future manipulations.

But the object is well created like that. You can delete it anywhere.

Personnaly, I prefer to have a delete function build-in, to not always writing display.remove(this) ; this=nil …

No need of finalize event.

my\_object.delete=function() my\_object:removeEventListener("enterFrame",my\_object) my\_object:removeEventListener("collision",my\_object) -- needed if collisions happens -- removes all references from my\_object in others tables my\_object:removeSelf() ; my\_object=nil end

Just call my_object.delete() once, anywhere.

transition.to(\_\_, { time=2000, x=100, y=100, onComplete=my\_object.delete } ) or timer.performWithDelay(1000,my\_object.delete)

or inside collisions functions

EDIT : I forgot to say that if your ennemies are deleted, they remains the bullets objects, and so the Runtime-collision detector continue running.

So delete the bullet when it’s needed, like after leaving the screen.

After deleting everything, or during a hide phase scene, write Runtime:removeEventListener(“enterFrame”,on_collision).

Thanks for the answer!

Making a delete function like this probably the best solution. I didn’t think about it.

Instead I wrote a finalize function for any of my object (the enemy was just an example) so that they look like this

local function create\_object() local object = display.newImageRect(...); --variables and stuff... function object:enterFrame() --[[object behaviour]]-- end function object.finalize() Runtime:removeEventListener(...); --and other events eventually linked to the object transition.cancel(self); object = nil end Runtime:addEventListener(...); object:addEventListener("finalize"); end

is it a good solution for performance? As there are going to be many different objects on the screen and many instanes of each of them.

Many object are just graphical effect so they create and destroy in a fraction, but it’s important to keep them as light as I can.

Another thing. As you wrote

in the create function, it will be usefull to return the object in case of future manipulations.

wouldn’t this make a new variable to set to nil when removing the object?

I mean if I wrote something like this:

local function create\_object() my\_object = display.newImageRect(...); --all the stuff for object behaviour end local function other\_example\_function() local created\_object = create\_object(); created\_object.x = 200; end

i would get two references to the same object. If the object eliminates himself from his enterFrame function, wouldn’t the second reference still keep the object in memory?

Hi, do some research into object pooling.  You shouldn’t be creating and destroying lots of objects like that it is so resource wasteful.

Thanks, it’s a good idea to save some resource, I’ll work on it!

@SGS: with your suggetion of using object pooling I improved a lot my game’s performance.

Though I still have some doubt about object reference. I noticed that if you get multiple variables referring to the same object, removing the object and setting to nil one of them does not remove the object table from the memory, as you can find if you try

local myObj = display.newImageRect(...); local second\_ref = myObj; display.remove(myObj); myObj = nil; print(second\_ref); --still exist print(second\_ref.x); print(second\_ref.xScale); --all the values still exist

Now, I’m not sure about what happens if the second variable referring the object is localized in a function. For example something like this

local function create\_enemy() local myEnemy = display.newImageRect(...); physics.addBody(myEnemy, {..}); myEnemy.myName = "enemy"; --all stuff that manage enemy behaviour function myEnemy:finalize() myEnemy = nil; end myEnemy:addEventListener("finalize"); end local function global\_collision(event) if (event.object1.myName=="enemy") and (event.objct2.myName=="bullet") or (--[[the same with object1 and object2 inverted]]) then local what\_object; if (event.object1.myName == "enemy") then what\_object = event.object1; else what\_object = event.object2; end display.remove(what\_object); end end

Now as you see I used a second variable referring to the same object to index it inside the global collision function, and I did not set it to nil at the end of the function. Would this force the app to keep in memory all the values inside the object table?

Another question is about transitions. In the documentation it says

Transitions that are applied to an object should be cancelled and set to nil before you remove the object. Since display objects are essentially Lua tables, one convenient method is to set the transition as a property of the display object itself. This allows you to easily access and cancel it.

Now, I neved did this, but always used transition.to function without any variable to keep its reference, and when removing object I always used

transition.cancel(myObject); display.remove(myObject); myObject = nil;

Would this force the app to keep in memory some information about transitions that are finished?

Hello,

I don’t clearly understand your questions.

In the create function, it will be usefull to return the object in case of future manipulations.

But the object is well created like that. You can delete it anywhere.

Personnaly, I prefer to have a delete function build-in, to not always writing display.remove(this) ; this=nil …

No need of finalize event.

my\_object.delete=function() my\_object:removeEventListener("enterFrame",my\_object) my\_object:removeEventListener("collision",my\_object) -- needed if collisions happens -- removes all references from my\_object in others tables my\_object:removeSelf() ; my\_object=nil end

Just call my_object.delete() once, anywhere.

transition.to(\_\_, { time=2000, x=100, y=100, onComplete=my\_object.delete } ) or timer.performWithDelay(1000,my\_object.delete)

or inside collisions functions

EDIT : I forgot to say that if your ennemies are deleted, they remains the bullets objects, and so the Runtime-collision detector continue running.

So delete the bullet when it’s needed, like after leaving the screen.

After deleting everything, or during a hide phase scene, write Runtime:removeEventListener(“enterFrame”,on_collision).

Thanks for the answer!

Making a delete function like this probably the best solution. I didn’t think about it.

Instead I wrote a finalize function for any of my object (the enemy was just an example) so that they look like this

local function create\_object() local object = display.newImageRect(...); --variables and stuff... function object:enterFrame() --[[object behaviour]]-- end function object.finalize() Runtime:removeEventListener(...); --and other events eventually linked to the object transition.cancel(self); object = nil end Runtime:addEventListener(...); object:addEventListener("finalize"); end

is it a good solution for performance? As there are going to be many different objects on the screen and many instanes of each of them.

Many object are just graphical effect so they create and destroy in a fraction, but it’s important to keep them as light as I can.

Another thing. As you wrote

in the create function, it will be usefull to return the object in case of future manipulations.

wouldn’t this make a new variable to set to nil when removing the object?

I mean if I wrote something like this:

local function create\_object() my\_object = display.newImageRect(...); --all the stuff for object behaviour end local function other\_example\_function() local created\_object = create\_object(); created\_object.x = 200; end

i would get two references to the same object. If the object eliminates himself from his enterFrame function, wouldn’t the second reference still keep the object in memory?

Hi, do some research into object pooling.  You shouldn’t be creating and destroying lots of objects like that it is so resource wasteful.

Thanks, it’s a good idea to save some resource, I’ll work on it!

@SGS: with your suggetion of using object pooling I improved a lot my game’s performance.

Though I still have some doubt about object reference. I noticed that if you get multiple variables referring to the same object, removing the object and setting to nil one of them does not remove the object table from the memory, as you can find if you try

local myObj = display.newImageRect(...); local second\_ref = myObj; display.remove(myObj); myObj = nil; print(second\_ref); --still exist print(second\_ref.x); print(second\_ref.xScale); --all the values still exist

Now, I’m not sure about what happens if the second variable referring the object is localized in a function. For example something like this

local function create\_enemy() local myEnemy = display.newImageRect(...); physics.addBody(myEnemy, {..}); myEnemy.myName = "enemy"; --all stuff that manage enemy behaviour function myEnemy:finalize() myEnemy = nil; end myEnemy:addEventListener("finalize"); end local function global\_collision(event) if (event.object1.myName=="enemy") and (event.objct2.myName=="bullet") or (--[[the same with object1 and object2 inverted]]) then local what\_object; if (event.object1.myName == "enemy") then what\_object = event.object1; else what\_object = event.object2; end display.remove(what\_object); end end

Now as you see I used a second variable referring to the same object to index it inside the global collision function, and I did not set it to nil at the end of the function. Would this force the app to keep in memory all the values inside the object table?

Another question is about transitions. In the documentation it says

Transitions that are applied to an object should be cancelled and set to nil before you remove the object. Since display objects are essentially Lua tables, one convenient method is to set the transition as a property of the display object itself. This allows you to easily access and cancel it.

Now, I neved did this, but always used transition.to function without any variable to keep its reference, and when removing object I always used

transition.cancel(myObject); display.remove(myObject); myObject = nil;

Would this force the app to keep in memory some information about transitions that are finished?