Luaの実行中にエラーがでて画面上に赤字でlua runtime error・・・の文字が出ることがあります。(lua compile error〜は又別の話)
このエラーが出るとそこでLuaの実行が中断してしまい、モデルが正常に動かなくなるなどすることがあります。
コレ自体、Luaが暴走してRCが本体ごと死んでしまう(無限ループとかの場合のように)のを防ぐための安全装置なのですが、不便です。
しかし、Luaにはこのような事態にも対処できる機能が備わっています。その名も"pcall関数"。詳しい説明は以下で。
通常の関数呼び出しは
func(arg1, arg2, arg3)
のように行います。コレに対してpcall関数を用いる場合は
pcall(func arg1, arg2, arg3)
のようにして、pcall関数を通して目的の関数を呼び出します。
この方法でfuncを呼ぶと、func関数の中で何かのエラーが起きた場合、Lua全体のエラーになる前にpcall関数が「エラーを捕まえて」もみ消して、
その上でpcall関数の返り値として"false, エラーメッセージ"の組を返してくれます。
コレによってpcallを呼び出した部分ではエラーが起きたかどうか分かり、対処することも可能となります。
尚、funcのなかでエラーが起きなかった場合、pcallの返り値は最初の1個がtrueで、続いてfuncの帰り値となるのでふつうに返り値を使うこともできます。
上記のように便利そうなpcallですが、実際に使うとめちゃくちゃ重いです。FPSが5くらい下がったとの報告もあります。
しかも、(モデルメインのLuaの場合)Luaで起きたエラーの詳細が分かったとして、対処方法は余りありません。
こういった理由により、実際のモデルではpcallが使われることは余りありませんが、
どんな場合にどんなエラーメッセージがでるのかを研究するのには便利でしょう。
RIAの特許っぽいんで許諾待ち
それなりに使えそうな定型表現と使用事例を集めてみました。
local flag, ret = pcall(func,args) if not flag then --適当なエラー処理のコード --out(0,ret) ・・・とか書いておくといいかもね! end
最も典型的な使い方です。こんなところでエラーを起こされたら困るんだ!という時に使いませう。シナリオなどファイル出力が可能な環境ならエラーログを吐き出すというのもアリ。エラーの赤文字が長すぎる、一瞬しか出てこないといった場合に結構助かります。
safe = false --グローバルなbooleanを用意しておくといいよ! function main() if safe then func2() else local flag, ret = pcall(func1) if not flag then safe = false --以後お好みのエラー処理でもどうぞ --ログ表示系を持つモデルならエラー文字列を表示してあげるとそれっぽいよ! --例えば MessageLog.Add(ret) とかそんな雰囲気で end end end
長くてちょっと分かり辛いですが、func1がエラーで止まったら以後func2が動くようなコードになります。func1を通常の操作系統、func2を非常用操作系統などと位置づけるとイメージがわき易いかもしれません。
こんな小細工が必要なほど複雑なモデルはそう多くないですが、どうもLuaの出来がイマイチでよくモデルが停止してしまう方、「非常系統」とか「予備系統」とかいった言葉に浪漫を感じる方は採用してみるといいかもしれません。
なお、ロールバック処理はfunc2に気合で書いてください。
pcall(require,"shared/SharedKeyAssign.lua")
このように記述すると、「ライブラリがロードできないからモデル動かねーYO!」というタイプのエラーを回避することができます。SharedKeyAssignのように、モデルを動かす人の環境によってあったりなかったりする類のライブラリを読み込む際にとても便利です。これが一番お手軽で実用的なpcallの使い方でもあります。