【问题标题】:lua - table maintenance (particle system related)lua - 表维护(粒子系统相关)
【发布时间】:2011-05-31 22:52:38
【问题描述】:

下面的update() 函数在游戏的每一帧都被调用。如果Drop 粒子的 y 值大于 160,我想将其从表中删除。问题是我收到“尝试将数字与 nil 进行比较”错误,如下所示:

local particles = {};

function update()
    local num = math.random(1,10);
    if(num < 4) then
        local drop = Drop.new()
        table.insert ( particles, drop );
    end

    for i,val in ipairs(particles) do
        if(val.y > 160) then --ERROR attempt to compare number with nil
            val:removeSelf(); --removeSelf() is Corona function that removes the display object from the screen
            val = nil;
        end
    end
end

我做错了什么?显然val 是 nil,但我不明白为什么表迭代会首先找到 val,因为当它的 y 值大于 160 时我将它设置为 nil。

【问题讨论】:

    标签: lua coronasdk lua-table particles


    【解决方案1】:

    感谢您的回答,他们都很有帮助。这就是最终为我工作的东西。 table.remove 调用是保持循环正常运行所必需的。

    for i = #particles, 1, -1 do
        if particles[i].y > 160 then
            local child = table.remove(particles, i)
            if child ~= nil then
                display.remove(child)
                child = nil
            end
        end
    end
    

    【讨论】:

      【解决方案2】:

      你找错地方了,问题不是val 是nil,而是val.y 是nil。看这个例子:

      > x=nil
      > if x.y > 10 then print("test") end
      stdin:1: attempt to index global 'x' (a nil value)
      stack traceback:
          stdin:1: in main chunk
          [C]: ?
      > x={y=nil}
      > if x.y > 10 then print("test") end
      stdin:1: attempt to compare number with nil
      stack traceback:
          stdin:1: in main chunk
          [C]: ?
      

      另外,当您将val 设置为nil 时,这可能不起作用(我相信val 是一个副本):

      > t={"a", "b", "c", "d"}
      > for i,val in ipairs(t) do print(i, val) end
      1   a
      2   b
      3   c
      4   d
      > for i,val in ipairs(t) do if i==3 then print("delete", val); val=nil end end
      delete  c
      > for i,val in ipairs(t) do print(i, val) end
      1   a
      2   b
      3   c
      4   d
      

      编辑:要从表中删除一个元素,你需要table.remove:

      > t[3]=nil
      > for i,val in ipairs(t) do print(i, val) end
      1   a
      2   b
      > t[3]="c"
      > for i,val in ipairs(t) do print(i, val) end
      1   a
      2   b
      3   c
      4   d
      > for i,val in ipairs(t) do if i==3 then print("delete", val); table.remove(t, i) end end
      delete  c
      > for i,val in ipairs(t) do print(i, val) end
      1   a
      2   b
      3   d
      

      【讨论】:

        【解决方案3】:

        JeffK 的解决方案应该有效,但我认为它有效的原因不是因为他正在向后遍历列表,而是因为他设置了particles[i] = nil 而不是val = nil。如果您运行val = nil,您只是将 val 的本地副本设置为 nil,而不是表中的条目。

        试试这个:

        for i,val in ipairs(particles) do
            if(val.y > 160) then
                particles[i]:removeSelf()
                particles[i] = nil;
            end
        end
        

        【讨论】:

        • 我试过你的代码。我现在没有收到错误,但奇怪的是它只会删除一个对象。之后,它再也不会进入 for 循环。这就像粒子表以某种方式设置为零。
        • 可能发生了什么然后列表中的第一个元素变为 nil'd,然后由于第一个元素为 nil,循环不再运行(因为迭代在到达 nil 索引时停止)。您可以通过在循环结束时压缩数组来解决这个问题,这样它就没有间隙,尽管这可能很棘手。
        • 是的,当达到nil 值时,for 循环将停止。我已经用正确执行删除的table.remove 更新了我的答案。
        【解决方案4】:

        我认为您不能在 ipairs 遍历表格时修改表格的内容。我依稀记得看过我的Lua 5.1 Reference Manual 的硬拷贝,但我现在似乎找不到它。当您将 val 设置为 nil 时,它会从 粒子 中移除一个元素em> 表。

        您可以尝试反向处理表格,因为您的函数正在全面扫描 particles 表格,有条件地删除一些项目:

        for x = #particles, 1, -1 do
            if particles[x].y > 160 then
                particles[x]:removeSelf()
                particles[x] = nil
            end
        end
        

        【讨论】:

        • 根据文档,警告仅适用于下一个和对。使用 ipairs 按数字顺序遍历表应该没问题。但是,他只是 niling val,而不是表中的条目lua.org/manual/5.1/manual.html#pdf-next
        • 我尝试了这段代码(在条件中添加 -1 并将粒子 [x].val 更改为粒子 [x].y 之后),但在删除粒子后我得到了这个:尝试索引场地 '?' (零值)
        • 根据 clua7 的 cmets 更新代码。 nil 引用错误令人费解。 removeSelf() 调用将对象与 Corona 的显示机制解除关联,并将其设置为 nil 会将其从 particles 表中删除,准备好进行垃圾回收。然后,x 应该递减,移动到表中的下一个对象。当您收到“尝试索引字段'时报告什么行?” (零值)?”
        猜你喜欢
        • 2012-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-09
        • 1970-01-01
        • 2011-04-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多