Lua 有效地从内存中删除对象

Lua 有效地从内存中删除对象,lua,coronasdk,Lua,Coronasdk,我在main.lua中有以下代码 我所要做的就是生成矩形,将它们添加到物理中,这样它们就可以从屏幕上掉下来,一旦它们的y大于屏幕高度(意味着它们不再可见),就从内存中删除矩形,还可以删除用户触摸到的那些矩形 这是我的密码 local physics = require( "physics") physics.start( ) --table to hold dynamically created rectangles local rects={} --used as index for tab

我在main.lua中有以下代码 我所要做的就是生成矩形,将它们添加到物理中,这样它们就可以从屏幕上掉下来,一旦它们的y大于屏幕高度(意味着它们不再可见),就从内存中删除矩形,还可以删除用户触摸到的那些矩形

这是我的密码

local physics = require( "physics")
physics.start( )

--table to hold dynamically created rectangles
local rects={}
--used as index for table
local numRect=0

--event handler for rectangle touch
local function rectTouch(event)
    event.target:removeSelf( )
    event.target = nil
end

--function for spawning rectangles
local function spawnRect()
    numRect = numRect + 1
    rects[numRect] = display.newRect( display.contentWidth/2, 200, 200, 200)
    rects[numRect]:setFillColor( 1,1,1 )
    physics.addBody( rects[numRect], "dynamic",{density=1, friction=0,2, bounce=0  })
    rects[numRect]:addEventListener( "touch", rectTouch )
end

--function for removing rectangles which are no more visible
local function removeInactiveRects()
    for i = 1, #rects do
        if rects[i] ~= nil  then
            if rects[i].y > display.contentHeight + 100 then
                rects[i]:removeSelf( )
                rects[i] = nil
            end
        end

    end
end



timer.performWithDelay( 1000, spawnRect, -1 )
timer.performWithDelay( 2000, removeInactiveRects,-1 )

我得到一个error removenactivesters函数,指出试图将数字与nil进行比较,我猜导致这种情况的语句是
rects[I]~=nil
,但我不知道为什么。此外,这是从内存中删除对象的正确方法吗?

问题在于触摸
rectTouch
功能,您不仅需要删除矩形,还需要删除
rects[]
表中的引用。您可以创建具有id值的矩形,以便能够在事件函数中识别它们并将其删除

--event handler for rectangle touch
local function rectTouch(event)
    local i = event.target.id
    event.target:removeSelf( )
    event.target = nil
    rects[i] = nil
end

--function for spawning rectangles
local function spawnRect()
    numRect = numRect + 1
    rects[numRect] = display.newRect( display.contentWidth/2, 200, 200, 200)
    rects[numRect]:setFillColor( 1,1,1 )
    rects[numRect].id = numRect
    physics.addBody( rects[numRect], "dynamic",{density=1, friction=0,2, bounce=0  })
    rects[numRect]:addEventListener( "touch", rectTouch )
end
我在科罗纳也是新来的,所以我不确定,但也许你可以在底部+500处创建一些“地面物体”,并检测碰撞以移除矩形。
查看问题在于触摸
rectTouch
功能,您不仅需要删除矩形,还需要删除
rects[]
表中的引用。您可以创建具有id值的矩形,以便能够在事件函数中识别它们并将其删除

--event handler for rectangle touch
local function rectTouch(event)
    local i = event.target.id
    event.target:removeSelf( )
    event.target = nil
    rects[i] = nil
end

--function for spawning rectangles
local function spawnRect()
    numRect = numRect + 1
    rects[numRect] = display.newRect( display.contentWidth/2, 200, 200, 200)
    rects[numRect]:setFillColor( 1,1,1 )
    rects[numRect].id = numRect
    physics.addBody( rects[numRect], "dynamic",{density=1, friction=0,2, bounce=0  })
    rects[numRect]:addEventListener( "touch", rectTouch )
end
我在科罗纳也是新来的,所以我不确定,但也许你可以在底部+500处创建一些“地面物体”,并检测碰撞以移除矩形。 查看

只需使用:

if rects[i] and rects[i].y > display.contentHeight + 100 then
发生这种情况是因为删除了一些矩形,所以它们在表中的索引为空。如果它是空的,那么很明显它不能有
.y
参数

您也可以通过如下方式插入对象来避免:

local localRect = display.newRect( display.contentWidth/2, 200, 200, 200)
rects:insert(localRect)
而不是使用

if rects[i] ~= nil then
使用

这意味着“如果在rects[i]中有任何对象(不是“nil”也不是“false”值)”

只需使用:

if rects[i] and rects[i].y > display.contentHeight + 100 then
发生这种情况是因为删除了一些矩形,所以它们在表中的索引为空。如果它是空的,那么很明显它不能有
.y
参数

您也可以通过如下方式插入对象来避免:

local localRect = display.newRect( display.contentWidth/2, 200, 200, 200)
rects:insert(localRect)
而不是使用

if rects[i] ~= nil then
使用


这意味着“如果在rects[i]中有任何对象(不是“nil”也不是“false”值)”

问题是语句
event.target=nil
也没有将相应的
rects[i]
设置为nil,它只会将目标从显示对象转换回常规表。因此,在该语句之后,
rects[i]
对应于触摸的目标的
i
包含一个常规表对象,而不是nil,并且该表对象没有y字段。每当在显示对象上
删除self
时,请确保从其他对象(如
rects
等表)中删除引用

此外,关于物体低于一定高度时的移除,有几种方法:

  • 一种是制作一个透明的几何体(如线),它是一个“isSensor”=真的物理体。在冲突处理程序中,必须使用timer.performWithDelay(function()event.target:removeSelf()end),因为不能立即删除属于冲突事件一部分的对象
  • 另一种方法是使用
    physicContact:isEnabled()
    ,并在冲突处理程序中禁用冲突并计划删除对象
  • 还有一种方法是在运行时对象上使用
    enterFrame
    ,并在其处理程序中检查是否有y>yMax的对象。可以立即移除这些对象
  • 最后,您使用的每2秒检查一次的技术也很有效 但是#4技术每2秒在所有“活动”框上循环一次,而基于物理的技术(#1和#2)只对那些应该移除的框使用计算周期。OTOH,碰撞检测本身有点苛刻,但在2D中可能没有这么多。
    enterFrame
    方法(#3)可能有点过火,因为它在每一帧(30次/秒)调用一次,而您只想删除对象以将物理从不再可见的不断演化的对象中解放出来,但不管是在对象通过阈值时还是在一秒钟后进行清理


    这一切都在日冕的碰撞文档中得到了解释

    问题在于语句
    event.target=nil
    没有将相应的
    rects[i]
    设置为nil,它只将目标从显示对象转换回常规表。因此,在该语句之后,
    rects[i]
    对应于触摸的目标的
    i
    包含一个常规表对象,而不是nil,并且该表对象没有y字段。每当在显示对象上
    删除self
    时,请确保从其他对象(如
    rects
    等表)中删除引用

    此外,关于物体低于一定高度时的移除,有几种方法:

  • 一种是制作一个透明的几何体(如线),它是一个“isSensor”=真的物理体。在冲突处理程序中,必须使用timer.performWithDelay(function()event.target:removeSelf()end),因为不能立即删除属于冲突事件一部分的对象
  • 另一种方法是使用
    physicContact:isEnabled()
    ,并在冲突处理程序中禁用冲突并计划删除对象
  • 还有一种方法是在运行时对象上使用
    enterFrame
    ,并在其处理程序中检查是否有y>yMax的对象。可以立即移除这些对象
  • 最后,您使用的每2秒检查一次的技术也很有效 但是#4技术每2秒在所有“活动”框上循环一次,而基于物理的技术(#1和#2)只对那些应该移除的框使用计算周期。奥托,碰撞