私はBitfighterのリードデベロッパで、主にC++で書かれたゲームですが、Luaを使ってロボットプレイヤーをスクリプトします。私たちはLunar(ルナの一種)を使ってビットを接着しています。ルアで古くなったC++リファレンスを検出する
私は現在、LuaのスクリプトがC++コードで参照されているオブジェクトが削除されていることを知ることができます。ここ
は(Luaの)いくつかのサンプルロボットのコードである:needTargetが真である場合に船にのみ設定されていることを
if needTarget then -- needTarget => global(?) boolean
ship = findClosest(findItems(ShipType)) -- ship => global lightUserData obj
end
if ship ~= nil then
bot:setAngleToPoint(ship:getLoc())
bot:fire()
end
お知らせ、そうでなければ、前の反復からの値が使用されています。変数が最後に設定されてから船が殺された(そしてC++によってそのオブジェクトが削除された)ことはかなり可能性があります(おそらく、ボットが仕事をしているということもあります:-)。もしそうなら、ship:getLoc()を呼び出すときにC++が適切に機能し、通常はクラッシュします。
したがって、プログラマが間違いを犯した場合に、どのようにして状況を最もうまく処理し、損害を制限するかが問題です。
私にはいくつかのアイデアがあります。
function itemDied(deaditem)
if deaditem == ship then
ship = nil
needTarget = true
end
end
第二には、私たちが「魔法」の問題を解決するために、スマートポインタを参照カウントのいくつかの並べ替えを実装することができます:船やその他の項目が死ぬとまず、C++のコードを呼び出すことができますLuaの機能のいくつかの並べ替えを作成することができます。しかし、私はこれでどこから始めるべきか分かりません。
if !isAlive(ship) then
needTarget = true
ship = nil -- superfluous, but here for clarity in this example
end
if needTarget then -- needTarget => global(?) boolean
ship = findClosest(findItems(ShipType)) -- ship => global lightUserData obj
end
<...as before...>
第四に、私は、船の唯一のIDを保持でき、ではなく:
第三に、我々はいくつかのdeadness検出器の一種(それがうまくいくかどうかはわかりません)ボットはそうのように呼び出すことができることを持つことができますこのような船オブジェクトに各サイクルを取得するための基準、および使用:
local ship = getShip(shipID) -- shipID => global ID
if ship == nil then
needTarget = true
end
if needTarget then -- needTarget => global(?) boolean
ship = findClosest(findItems(ShipType)) -- ship => global lightUserData obj
shipID = ship:getID()
end
<...as before...>
私の理想的な状況にもインテリジェントにエラーをスローしていました。私が死んだ船でgetLoc()メソッドを実行した場合は、ボットに復旧の機会を与えるか、少なくともシステムをロボットを殺して問題を記録するようにエラー処理コードをトリガーしたいと思います。私のボットをどのようにコード化するかにもっと注意する必要があります。
これは私の考えです。私は#1に傾いていますが、厄介な気がします(弾丸のような短いライフサイクルのオブジェクトがたくさんあるので、多くのことが往復しているかもしれませんが、ほとんどは追跡しません)。 itemDied()関数の実装を忘れることは簡単かもしれません。 #2は魅力的ですが、私は魔法が好きですが、どのように動くか分かりません。 #3 &#4は非常に分かりやすく、いくつかのゲームサイクル(おそらく単一の船)の間に面白い少数のオブジェクトにしか私の死の検出を制限することはできません。
これは一般的な問題です。あなたはこれらのアイデアをどう思いますか、そこには優れたものがありますか?
ありがとうございます!
ここに私の現在の最善の解決策だ:C++で
、私の船のオブジェクトは、そのライフサイクルC++によって制御されている船、と呼ばれています。各Shipに対して、私はShuaへのポインタを含むLuaShipと呼ばれるプロキシオブジェクトを作成し、ShipにはLuaShipへのポインタが含まれています。Shipのデストラクタでは、LuaShipのShipポインタをNULLに設定しました。これは、船が破壊されたという指標として使用されます。
私のLuaコードはLuaShipへの参照しか持っていないので、理論的には少なくともこの部分は依然として適切に機能していません。Luaは対応するShipオブジェクトがなくなるとLuaShipのライフサイクルを制御します。したがって、Shuaオブジェクトがなくなっても、Luaは常に有効なハンドルを持ち、ShipがNULLであることをチェックするShipメソッドのプロキシメソッドを書くことができます。
これで私の仕事は、Luna/Lunarがポインタのライフサイクルをどのように管理しているかをよりよく理解することです。また、Luaコードを指し示しているLuaコードが残っていると、それは非常にやりやすいはずです。
実際、少なくとも私によってではないことが判明しました。何がうまくいくかは、ShipとLuaShipのオブジェクトを少し切り離すことでした。さて、LuaスクリプトがLuaShipオブジェクトをリクエストすると、新しいものを作成してLuaに渡し、Luaがそれを完了したら削除します。 LuaShipはスマートポインタを使用してShipを参照するため、Shipが終了すると、そのポインタはNULLに設定され、LuaShipオブジェクトが検出できます。
Luaコーダーは、使用する前に船がまだ有効であることを確認する必要があります。もしそうでなければ、(前に起こったように)ゲーム全体がクラッシュするのではなく、召喚を捕まえて、厳しいエラーメッセージを投げ捨てることができます。
LuaはLuaShipのライフサイクルを完全に制御でき、C++は問題を起こすことなく船を削除することができ、すべてがスムーズに動作するようです。唯一の欠点は、私が潜在的に多くのLuaShipオブジェクトを作成していることですが、それほど悪くはありません。
あなたは、このトピックに興味がある場合は、上記を精製するためにいくつかの提案で終わること、私は関連する概念について投稿メーリングリストのスレッドを参照してください。
http://lua-users.org/lists/lua-l/2009-07/msg00076.html
あなたは[luabridge](https://github.com/vinniefalco/LuaBridge)や[luabind](http://www.rasterbar.com/products/luabind/docs.html)のようなもっと精巧なものを試してみましたか? )?どちらもメモリリークのない寿命が長い(lua/C++)オブジェクトを許可します –