I used to have all my object being created in the main game loop… this caused a lot of lag after a couple of minutes playing the game. I fixed this by creating everything outside the loop and just updating positions in the loop. Now when I run the game in the corona simulator I don’t get any noticeable lag, but when I try the game on my Android tablet it lags like before. What could be the reason for this? What lags is the arrow moving by the enterFrame listener and the ball which is a physical body moved by the applyLinearImpulse command.
Lag can be caused by many different things:
-
Too many display objects. (Can only be determined through testing.)
-
Too many physics bodies. (Can only be determined through testing.)
-
Too many moving objects. (Can only be determined through testing.)
-
Poorly tuned physics settings. (Can only be determined through testing.)
-
Too many enterFrame listeners and or timers. (Can only be determined through testing, but best practices can avoid or at least alleviate this problem.)
-
Dead code that is still running. i.e. It has no purpose, but you didn’t clean it up correctly. (This is something experience will help you avoid.)
Debugging Tip & Action Request
A. Set your target FPS to 30 (in config.lua)
B. Measure: FPS and memory usage and tell us what you’re seeing.
https://roaminggamer.github.io/RGDocs/pages/SSK2/libraries/meters/#meters-sskmeters
C. With regards to memory, does it just keep increasing over time?
I tested it on my PC’s simulator, on my phone, and on my tablet. On the PC the FPS rate stayed between 62 and 68, main memory starts at 1.5 MB and keeps going up, texture memory starts at 98 and keeps increasing. On my phone, the FPS rate remained between 60 and 65, main memory was similar to PC ( 1.5 MB and going up), texture memory starts at 60 MB and goes up. On my tablet however, the frame rate would start off at 60, but it would keep going down and down (I stopped tracking when it reached 20 FPS), main memory, like the PC and phone, started at 1.5 MB and kept going up gradually, Texture memory started around 43 MB and also kept increasing.
Any ideas what’s causing it, and why the frame rate only decreases on my tablet?
Does it have anything to do with the PC and Phone having a bigger RAM capacity than the tablet?
You have probably memory leak.
Try to put all your value in global and see if it’s change something (perhaps hard to do it but prevent memory leak)
When you have found your memory leak go back to all private value
Okay I found the cause of the lag. It’s the a tap listener, I tried deleting different parts of my code, removing the tap listener is the only thing that stopped the lag. So now I’m sure it’s the cause, how do I fix it? Here is the code:
[lua] local function pushBall()
Runtime:removeEventListener(“enterFrame”, doTurn)
ball:removeEventListener( “tap”, pushBall )
shots = shots + 1
local collide = 0
arrow.isVisible = false
globalData.playerselected.isVisible = false
local ang = arrow.rotation
globalData.kick.isVisible = true
globalData.kick.x = 0.1 * centerX
globalData.kick.y = 530
ball:applyLinearImpulse( math.cos( math.rad( ang ) )*100, math.sin( math.rad( ang ) )*100 , ball.x, ball.y )
entered = false
goal.preCollision = preCollide
goal:addEventListener(“preCollision”)
goal.postCollision = postCollide
goal:addEventListener(“postCollision”)
goal:addEventListener(“collision”, goal)
local reset = function() return resetBall(startingPosition) end
timer.performWithDelay( 1000, reset, 1 )
end
ball:addEventListener( “tap”, pushBall )[/lua]
I don’t necessarily believe it is the ‘tap’ listener, but rather something that happens when it runs. Have you tried:
- Not removing it
- Not interacting with the game (just let it sit on the play scene)
If you do this, does memory usage increase?
As far as your tap listener, I’m not clear what you’re doing there, but I find it somewhat troubling that:
- You didn’t use a local listener
- You’re doing a lot of listener adding to some other object in the tap listener. i.e. Indicates to me that you might end up adding multiple duplicate listeners to ‘goal’.
- tap listeners are inferior and I never use them. I always use touch and the phases of a touch to make clear decisions on logic.
Again, it is very hard to tell what you’re doing since that is completely out of context.
When I don’t interact it’s fine. But when I do tap that’s when memory increases and lag begins. Note that in the reset function it checks for highscore then I call the function main which stores the the starting coordinates of my objects, as well as all the listeners. I do this to reset everything basically, is that what’s causing the lag?
This is the kind of thing that would take in-depth hands-on debugging.
Your options are:
-
Continue this thread and hope someone sees something I’m missing that will solve the problem. Possible, but I think there may be more issues.
-
Get hands-on help from someone who has time to do so for free.
-
Pay someone to review your game and help narrow down the issue.
-
Re-write it. I know this sounds terrible, but this is how I learned. I wrote a game or app. Then I re-wrote it better. Along the way I learned things and my coding skills increased till I had issues less and less often.
Best of luck to you on this. You can resolve it.
OK so now you simplify the code (comment lines out one at a time) running in the tap listener until you find the cause of your lag.
I don’t know what you mean by ‘reset’ listeners, but I can see you’ve got a major issue with the way you’re coding your listener (the one you showed).
This is how you coded it:
local function someName() end obj:addEventListener( "tap", someName )
This is a much much better way to do do it:
function obj.tap( self, event ) end obj:addEventListener( "tap" )
This way , the listener is auto-removed when you delete the object. As well, it is scoped directly to the object in question so you can refer to ‘self’ in the listener body and you’ll be operating on that specific object.
The above approach works for tap, touch, finalize , collision, preCollision, postCollision, and similar listeners.
There is a similar style of coding for Runtime events, but you must clean up the listener yourself. Here is an example for enterFrame:
local obj = display.newCircle( 10, 10, 10 ) function obj.enterFrame( self ) self.x = self.x + 1 end Runtime:addEventListener( "enterFrame", obj ) -- Use finalize to clean up listener when obj is deleted. function obj.finalize( self ) Runtime:removeEventListener( "enterFrame", self ) end obj:addEventListener("finalize")
Lag can be caused by many different things:
-
Too many display objects. (Can only be determined through testing.)
-
Too many physics bodies. (Can only be determined through testing.)
-
Too many moving objects. (Can only be determined through testing.)
-
Poorly tuned physics settings. (Can only be determined through testing.)
-
Too many enterFrame listeners and or timers. (Can only be determined through testing, but best practices can avoid or at least alleviate this problem.)
-
Dead code that is still running. i.e. It has no purpose, but you didn’t clean it up correctly. (This is something experience will help you avoid.)
Debugging Tip & Action Request
A. Set your target FPS to 30 (in config.lua)
B. Measure: FPS and memory usage and tell us what you’re seeing.
https://roaminggamer.github.io/RGDocs/pages/SSK2/libraries/meters/#meters-sskmeters
C. With regards to memory, does it just keep increasing over time?
I tested it on my PC’s simulator, on my phone, and on my tablet. On the PC the FPS rate stayed between 62 and 68, main memory starts at 1.5 MB and keeps going up, texture memory starts at 98 and keeps increasing. On my phone, the FPS rate remained between 60 and 65, main memory was similar to PC ( 1.5 MB and going up), texture memory starts at 60 MB and goes up. On my tablet however, the frame rate would start off at 60, but it would keep going down and down (I stopped tracking when it reached 20 FPS), main memory, like the PC and phone, started at 1.5 MB and kept going up gradually, Texture memory started around 43 MB and also kept increasing.
Any ideas what’s causing it, and why the frame rate only decreases on my tablet?
Does it have anything to do with the PC and Phone having a bigger RAM capacity than the tablet?
You have probably memory leak.
Try to put all your value in global and see if it’s change something (perhaps hard to do it but prevent memory leak)
When you have found your memory leak go back to all private value
Okay I found the cause of the lag. It’s the a tap listener, I tried deleting different parts of my code, removing the tap listener is the only thing that stopped the lag. So now I’m sure it’s the cause, how do I fix it? Here is the code:
[lua] local function pushBall()
Runtime:removeEventListener(“enterFrame”, doTurn)
ball:removeEventListener( “tap”, pushBall )
shots = shots + 1
local collide = 0
arrow.isVisible = false
globalData.playerselected.isVisible = false
local ang = arrow.rotation
globalData.kick.isVisible = true
globalData.kick.x = 0.1 * centerX
globalData.kick.y = 530
ball:applyLinearImpulse( math.cos( math.rad( ang ) )*100, math.sin( math.rad( ang ) )*100 , ball.x, ball.y )
entered = false
goal.preCollision = preCollide
goal:addEventListener(“preCollision”)
goal.postCollision = postCollide
goal:addEventListener(“postCollision”)
goal:addEventListener(“collision”, goal)
local reset = function() return resetBall(startingPosition) end
timer.performWithDelay( 1000, reset, 1 )
end
ball:addEventListener( “tap”, pushBall )[/lua]
I don’t necessarily believe it is the ‘tap’ listener, but rather something that happens when it runs. Have you tried:
- Not removing it
- Not interacting with the game (just let it sit on the play scene)
If you do this, does memory usage increase?
As far as your tap listener, I’m not clear what you’re doing there, but I find it somewhat troubling that:
- You didn’t use a local listener
- You’re doing a lot of listener adding to some other object in the tap listener. i.e. Indicates to me that you might end up adding multiple duplicate listeners to ‘goal’.
- tap listeners are inferior and I never use them. I always use touch and the phases of a touch to make clear decisions on logic.
Again, it is very hard to tell what you’re doing since that is completely out of context.
When I don’t interact it’s fine. But when I do tap that’s when memory increases and lag begins. Note that in the reset function it checks for highscore then I call the function main which stores the the starting coordinates of my objects, as well as all the listeners. I do this to reset everything basically, is that what’s causing the lag?
This is the kind of thing that would take in-depth hands-on debugging.
Your options are:
-
Continue this thread and hope someone sees something I’m missing that will solve the problem. Possible, but I think there may be more issues.
-
Get hands-on help from someone who has time to do so for free.
-
Pay someone to review your game and help narrow down the issue.
-
Re-write it. I know this sounds terrible, but this is how I learned. I wrote a game or app. Then I re-wrote it better. Along the way I learned things and my coding skills increased till I had issues less and less often.
Best of luck to you on this. You can resolve it.
OK so now you simplify the code (comment lines out one at a time) running in the tap listener until you find the cause of your lag.
I don’t know what you mean by ‘reset’ listeners, but I can see you’ve got a major issue with the way you’re coding your listener (the one you showed).
This is how you coded it:
local function someName() end obj:addEventListener( "tap", someName )
This is a much much better way to do do it:
function obj.tap( self, event ) end obj:addEventListener( "tap" )
This way , the listener is auto-removed when you delete the object. As well, it is scoped directly to the object in question so you can refer to ‘self’ in the listener body and you’ll be operating on that specific object.
The above approach works for tap, touch, finalize , collision, preCollision, postCollision, and similar listeners.
There is a similar style of coding for Runtime events, but you must clean up the listener yourself. Here is an example for enterFrame:
local obj = display.newCircle( 10, 10, 10 ) function obj.enterFrame( self ) self.x = self.x + 1 end Runtime:addEventListener( "enterFrame", obj ) -- Use finalize to clean up listener when obj is deleted. function obj.finalize( self ) Runtime:removeEventListener( "enterFrame", self ) end obj:addEventListener("finalize")