1耘擂、背景
??在Lua寫了個GameObject的對象池,在某個特殊地方發(fā)現(xiàn)旱物,GameObject還存在遥缕,但是Lua里訪問報錯,提示對象是nil宵呛。經(jīng)過一番查找单匣,發(fā)現(xiàn)是Lua弱引用GameObject+GC導(dǎo)致的。有時候多想一點宝穗,反而容易導(dǎo)致問題Orz……記錄一點現(xiàn)象留念吧户秤。
2、環(huán)境
- Unity 5.4.5p4 (64-bit)
- ToLua#1.02(Lua5.1)
3逮矛、記錄
3.1 弱引用緩存GameObject實例
??這里我將table的key標記為弱引用
function PrefabPool:SetPrefab(name, prefab)
self._prefabs[name] = prefab
self._gos[name] = setmetatable({}, {__mode='k'})
end
-- 緩存對象
if go then
self._gos[prefab_name][go] = true
go:SetActive(true)
end
3.2 引發(fā)問題
??Lua中沒有額外引用時鸡号,調(diào)用GC。
- Lua里:
collectgarbage("collect")
- C#里:
LuaState.LuaGC(LuaGCOptions.LUA_GCCOLLECT);
上面兩種方式應(yīng)該是等價的须鼎。
3.3 問題現(xiàn)象
??LuaGC之后膜蠢,GameObject對象其實還是存在的堪藐,并且在Hierarchy中還可以看到,但是Lua中變成了這樣
Lua中被銷毀的狀態(tài).png
正常情況
??使用Debug.LogError(tostring(k), type(k))
輸出緩存挑围,甚至能看到奇怪的現(xiàn)象:
- [ERROR]nil, userdata
- [ERROR]null, userdata
- [ERROR]Image_CardCombo (UnityEngine.GameObject), userdata
- [ERROR]Image_PlayerIcon (UnityEngine.UI.Image), userdata
- [ERROR]Image_CommandIcon (UnityEngine.UI.Image), userdata
上面這些全部是GC后輸出的內(nèi)容礁竞,其中nil是GC后馬上輸出看到的,而其余的是多跑兩場戰(zhàn)斗杉辙、切個場景后輸出的模捂。后面幾項輸出的結(jié)果,具有隨機性蜘矢,并且都不是我緩存池管理的對象狂男。因此我有個推測:
LuaGC后的C#對象具有不穩(wěn)定性,在某些條件的觸發(fā)下品腹,會指向其他對象岖食。(有點野指針的趕腳)
[2018-1-4] 今早找蒙哥請教了下這個問題:
- gc之后壓入就是新的 肯定不一樣
- 早期有個bug,觸發(fā)異常gc后每次壓入都是新的(就是沒有g(shù)c觸發(fā)舞吭,但一個對象壓入時已經(jīng)不在luavm里面了)
由于項目比較緊張泡垃,不方便升級,我這里暫時取消弱引用的方式羡鸥。