他のほとんどの種類の Stingray リソースと同様に、ゲームの実行中に Lua スクリプトを修正して再コンパイルし、ゲームをその場で再ロードすることができます。これは、新しい変更をデバッグしてテストするときに、反復時間を短縮するのに役立つ強力なメカニズムです。Stingray アセットの一般的なライブ再ロードの背景情報については、「リソースの再ロード」も参照してください。
このページでは、Lua スクリプトを再コンパイルして再ロードする方法、および Lua スクリプトをゲームに再ロードするときに適用されるいくつかの特殊な考慮事項の詳細について説明します。
スクリプト内で変更を行い、プロジェクト フォルダに保存します。
スクリプトを保存するとすぐに再コンパイルされるわけではありません。スクリプトを再コンパイルするよう指示する必要があります。Stingray エディタで[F5]を押すか、メイン メニューで Edit > Level Testing > Refresh を選択します。このスクリプトの新しいバージョンを使用して、コンパイル済みデータのフォルダが更新されます。
ステータス バーから refresh コンソール コマンドを発行して、ゲームのスクリプトを再ロードしてください。「ステータス バーからコマンドを送信する」を参照してください。
「リソースの再ロード」も参照してください。
エンジンは Lua ファイルを再ロードするときに、ファイル全体を単に再実行します。これにより、すべての定義が再評価され、すべての変数および関数が再定義されます。この操作を行うと、予期しない副作用が生じることがあります。
最初に認識しなければならないのは、スクリプトで定義した関数は新しいコードに合わせてランタイムの Lua 環境で再定義されますが、これらの関数は必ずしも呼び出されるとは限らないことです。
たとえば、グローバルな init() 関数をブート スクリプト内で記述し直した場合、これらの変更は現在のゲームの状態に影響しません。なぜなら、init() 関数はゲームを最初に起動したときに、古いコンテンツを使用して呼び出されたためです。したがって、これによって実行されたすべての定義は引き続き有効であり、新しい実装でユーザが行った操作は効果がありません。
この考慮事項は、他の種類のオブジェクトの初期化にも適用されます。たとえば、スポーンされた時点における特定の特性セットを使用してユニットを初期化するとします。その後、ユニットをスポーンする関数を修正して、これらの特性を変更し、スクリプトを再ロードします。この場合、再ロード後にスポーンした新しいユニットには変更を適用できますが、既にスポーンされているユニットには変更が適用されません(新しいユニットをスポーンするときに、新しいコードが適切に呼び出されると仮定します)。
新しいテーブル変数を作成した場合、Lua は「参照」を使用してこの変数がテーブルを指すように設定します。2 番目の引数が最初の引数と同じ場合、2 番目の変数には同じ参照が格納されます。後で新しいテーブルを指すように最初の変数を再定義した場合も、2 番目の変数は引き続き元のテーブルを指します。
たとえば、プロジェクト内で Appkit を使用していて、次のコードを含む project.lua スクリプトがあるとします。
Project = {} function Project.update(dt) print("hello.") end
ゲームの起動時に Appkit の SimpleProject.extension_project 変数には Project テーブルに対する参照が次のように格納されます。
if Project then SimpleProject.extension_project = Project end
Project.update() 関数によって出力される文字列を変更して、project.lua スクリプト ファイルを再ロードするとします。この場合、フレームごとにログに新しい文字列が出力されると予測されますが、実際は、古い文字列が引き続き出力されます。
この動作の原因は、ゲームがこの行を再実行するときに、次のようになるためです。
Project = {}
新しいテーブル参照が作成され、グローバルな Project 変数に格納されます。この新しいテーブルには、新しい文字列を使用する update() 実装が割り当てられます。ただし、SimpleProject.extension_project 変数は引き続き、グローバルな Project 変数が参照していた古いテーブルを指しています。
この問題を回避するには、グローバル テーブルを定義するときに、次の式を使用することをお勧めします。
Project = Project or {}
この式を使用すると、スクリプトを再ロードして、この行を再実行したときに、Project 変数は既に存在するため、新しいテーブルは作成されません。代わりに、ファイルの残りの部分にある関数およびメンバーの定義が既存のテーブルに適用されます。したがって、update() 関数によって出力される文字列を変更すると、その変更がフレームごとに SimpleProject で考慮されます。
スクリプトによって他の種類のテーブル以外の値がキャッシュされる場合、キャッシュされたこれらの値を更新するには、変数を初期化したコードを再実行する必要があります。
たとえば、次のコードがあるとします。
Project = Project or {} function Project.update(dt) print("hello.") end
前のセクションで説明したように、Project テーブルを指す変数が他の場所に格納されている場合に、フレームごとに update() 関数を呼び出すと、再ロード後は常に最新バージョンの Project.update() が使用されます。ただし、Project.update() 関数自体を直接指す変数が格納されている場合、この変数は再ロード後も古い関数を使用し続けます。
同じことは、文字列やメンバーといった他の Lua 変数の型にも適用されます。