Corona SDK / Lua / 内存泄漏

我正在开发一个游戏时,有一个名为“rain”的模块导致了严重的系统内存泄漏,导致应用程序最终崩溃。 每50毫秒调用一次“t.start”函数,尝试了很多方法也没能找到原因!也许我忽略了一些东西,但我无法想到原因。如您所见,我已经将与图形相关的本地变量删除了...有没有人注意到什么吗?

次要问题:有没有人有关于如何预加载下一个场景使场景切换更流畅的提示?因为场景加载本身会导致短暂的冻结,当我将其放入“场景:show()”中...

感谢您的帮助! 问候, Nils

local t = {}
    local composer = require("composer")
    t.drops = {}

    function t.fall(drops, group)
        for i = 1, #drops, 1 do
            local thisDrop = drops[i]
            function thisDrop:enterFrame()
                if aboutToBeDestroyed == true then
                    Runtime:removeEventListener("enterFrame", self)
                    return true
                end
                local randomY = math.random(32, 64)
                if self.x ~= nil then
                    self:translate(0, randomY)
                    if self.y > 2000 then
                        self:removeSelf()
                        Runtime:removeEventListener("enterFrame", self)
                        self = nil
                    end
                end
            end
            Runtime:addEventListener("enterFrame", drops[i])
            thisDrop = nil
        end
    end

    t.clean = function()
        for i = 1, #t.drops, 1 do
            if t.drops[i] ~= nil then
                table.remove(t.drops, i)
                t.drops[i] = nil
            end
        end
    end

    function t.start(group)
        local drops = {}
        local theGroup = group
        for i = 1, 20, 1 do
            local randomWidth = math.random(5, 30)
            local dropV = display.newRect(group, 1, 1, randomWidth, 30)
            local drop1 = display.newSnapshot(dropV.contentWidth , dropV.contentHeight * 3)
            drop1.canvas:insert(dropV)
            drop1.fill.effect = "filter.blurVertical"
            drop1.fill.effect.blurSize = 30
            drop1.fill.effect.sigma = 140
            drop1:invalidate("canvas")
            drop1:scale(0.75, 90)
            drop1:invalidate("canvas")
            drop1:scale(1, 1 / 60)
            drop1:invalidate("canvas")
            local drop = display.newSnapshot(drop1.contentWidth * 1.5, drop1.contentHeight)
            drop.canvas:insert(drop1)
            drop.fill.effect = "filter.blurHorizontal"
            drop.fill.effect.blurSize = 10
            drop:invalidate("canvas")
            drop.alpha = 0.375
            local randomY = math.random(-500, 500)
            drop.y = randomY
            drop.anchorY = 0
            drop.x = (i - 1) * 54
            drops[i] = drop
            table.insert(t.drops, drop)
            local dropV, drop1, drop = nil
        end
        composer.setVariable("drops", t.drops)
        t.fall(drops, group)
        drops = nil
        t.clean()
    end
return t

EDIT:我发现这绝对与嵌套的快照有关,用于应用滤镜效果。我删除了一个快照,所以我只有一个快照中的矢量对象,内存增长速度慢了很多。问题是:为什么?

点赞
用户5331361
用户5331361

通常情况下,您根本不需要使用enterFrame事件--您可以从起始点(math.random(- 500,500))到终点(您代码中的2000)进行转换。只需随机速度并使用完成后处理程序来移除对象

local targetY = 2000
local speedPerMs = math.random(32, 64) * 60 / 1000
local timeToTravel = (targetY - randomY) / speedPerMs
transition.to(降,{
时间= timeToTravel,
    x = xx,
    y = targetY,
完成 = function()
        丢弃:removeSelf()
    end
})

编辑1:我发现使用您的代码仅仅移除下降物是不够的。这对我起作用:

掉落:removeSelf()
dropV:removeSelf()
掉落1:removeSelf()

有关内存消耗的一些想法:

1)可能你可以为落下物的数组使用1个enterFrame处理程序--这将减少内存消耗。此外,不要向本地对象添加方法,例如 'function thisDrop:enterFrame()' - 这在这里不是最佳选项,因为您每50毫秒创建20个新函数

2)您的代码每秒创建400个'drop'对象,它们通常的寿命不超过〜78帧(在60fps环境中为1.3秒)。最好使用对象池并重复使用现有对象

3)enterFrame函数取决于设备的当前fps,因此您的雨会因低fps而变慢。低fps->对象下降得更慢->场景上有更多对象->fps下降。建议您计算两个enterFrame调用之间的deltaTime,并根据deltaTime调整下落速度

编辑2似乎:snapshot的removeSelf()没有删除子对象。我修改了您的代码,并且内存消耗大大降低。

if self.y > 2000 then
    local drop1 = self.group[1]
    local dropV = drop1.group[1]
    dropV:removeSelf()
    drop1:removeSelf()
    self:removeSelf()
    Runtime:removeEventListener(“enterFrame”,selfself = nil
end
2017-03-17 13:15:07