【发布时间】:2014-06-04 04:43:12
【问题描述】:
我是 Lua 的新手。我正在尝试使用 Cocos2d-x v3.1rc0 创建游戏。
我遇到了一个问题,其中一个由 Cocos2d-x 库创建的对象似乎在应该被垃圾收集之前被垃圾收集了。
这是一个跟踪屏幕上“猎物”的类。每个猎物都会引用将根据猎物状态显示的帧/动画。
Prey = {
sprite = false -- Main prey sprite.
-- Frames used for movement, getting hit, knocked out, etc.
, frame = {
idle = false -- idle frames
, move = false -- move frames
, rest = false -- resting frames
}
, state = false -- The current state of the Prey.
}
这里是构造函数:
function Prey:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
这是帧与猎物相关联的位置:
function Prey:setFrames(frames)
--[[ Moving ]]--
self.frame.move = cc.Animation:createWithSpriteFrames({frames[1], frames[2], frames[3]}, 1.0)
cclog("move frames: " .. #self.frame.move:getFrames())
--[[ Resting ]]--
self.frame.rest = cc.Animation:createWithSpriteFrames({frames[4], frames[5]}, 2.0)
cclog("rest frames: " .. #self.frame.rest:getFrames())
end
上面将打印以下内容:
cocos2d: [LUA-print] move frames: 3
cocos2d: [LUA-print] rest frames: 2
但是,当我尝试调用以下方法时,frame.move 和 frame.rest 变量似乎已被垃圾回收,因为当我尝试访问它们时会引发错误。请注意,此方法在每个刻度上都会调用:
function Prey:tick()
cclog("state: " .. self.state)
local animation = false
-- Moving
if (self.state == PreyState.MOVING)
then
cclog("moving: " .. #self.frame.move:getFrames())
animation = self.frame.move
elseif (self.state == PreyState.RESTING)
then
cclog("resting: " .. #self.frame.rest:getFrames())
-- Resting
animation = self.frame.rest
end
end
当针对这两种情况之一进行 cclog 调用时,将显示以下错误。请注意,我知道 Prey 的这个特定实例没有被垃圾回收,因为在我调用 tick 方法之前 self.state 被设置为空闲。它还在对该方法的后续调用中保留 self.state。
cocos2d: [LUA-print] state: 2
cocos2d: [LUA-print] ----------------------------------------
cocos2d: [LUA-print] LUA ERROR: [string "Prey.lua"]:189: invalid 'cobj' in function 'lua_cocos2dx_Animation_getFrames'
在查看了许多描述如何保留对象的文章之后,似乎我的 Animation 对象可能正在被垃圾收集。但我不知道为什么!对 Cocos2d-x 对象的引用应该很强吧?
以下是我读过的一些关于该主题的文章:
- http://www.tutorialspoint.com/lua/lua_object_oriented.htm
- http://lua-users.org/wiki/WeakTablesTutorial
- http://www.lua.org/pil/17.html
- http://phrogz.net/lua/LearningLua_ValuesAndMetatables.html
- http://lua-users.org/wiki/GarbageCollectionTutorial
更新 1
以下代码是导致问题的原因:
-- Create the instance of our prey object here...
prey = new Prey:new()
local function tick()
prey:tick()
end
scheduleID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(tick, 0, false)
但是,当我尝试在调度程序之外简单地调用 prey:tick() 时,我没有收到任何错误。我需要在每一次滴答声中运行这段代码......我错过了什么?在这个特定的场景中,我将prey 设为全局变量,以便 tick 方法可以访问 Prey 的唯一实例。我这样做是为了简化这个特定的测试。但是,我想让 prey 本地化并让调度程序为 Prey 的每个实例运行 tick 函数。
【问题讨论】:
-
好吧,这似乎不是表格的问题。当我将 Cocos2d-x 对象的引用移动到不属于该类的全局变量中时,它仍然会产生该错误。
-
我只能在创建它的块的上下文中引用一个 Cocos 对象吗?这看起来真的很傻。
标签: lua garbage-collection cocos2d-x cocos2d-x-3.0