0

ゲームエンジンのロジックにはLuaを使用しています。私のメインのゲームループはLuaでは実行されません。シーン階層内の特別なノードのみにLuaスクリプトが添付されています。これらのスクリプトはフレームごとに実行されます。私が直面している問題は、グローバル変数の値をあるフレームから別のフレームに保持する必要があることです。

私の一時的な解決策は次のようになります。

finish = useBool("finish", false)
timer = useInt("timer", 0)
showTimer = useBool("showTimer", true)
startTimer = useInt("startTimer", 0)
play0 = useBool("play0", false)
play1 = useBool("play1", false)
play2 = useBool("play2", false)
play3 = useBool("play3", false)
delta = useInt("delta", 0)
gameOverTime = useInt("gameOverTime", 5000)
finishTime = useInt("finishTime", 5000)
checkPoint = useInt("checkPoint", 255)

<...> Game logic <...>

setInt("message", message);
setInt("checkPoint", checkPoint)
setInt("finishTime", finishTime)
setInt("gameOverTime", gameOverTime)
setInt("timer", timer)
setBool("play3", play3)
setBool("play2", play2)
setBool("play1", play1)
setBool("play0", play0)
setInt("startTimer", startTimer)
setBool("showTimer", showTimer)
setInt("timer", timer)
setBool("finish", finish);

最初にC++のハッシュマップからグローバル変数を取得する特別なメソッドを呼び出し、スクリプトの最後にそれらを再度設定します。

これを暗黙的に行う方法はありますか?

Luaをメインのゲームループとして使用しないのは悪いデザインですか?

4

1 に答える 1

3

ソリューションに技術的な問題はありませんが、グローバル変数が多数ある場合(一般的には避けるべきもの)、パフォーマンスの問題に気付く可能性があります。

そうは言っても、改善の余地があります。例えば:

スクリプトの開始時に、グローバル変数がであるかどうかを確認しますnil。そうである場合は、初期化できます。そうでない場合は、スクリプトを実行するのはこれが初めてではない可能性があるため、変更しないでください。しかし、それは多くの厄介なif-else発言を意味し、それは簡単に忘れることができます。私たちはもっとうまくやれる!

『Programming in Lua』の本の第14章:環境を参照することをお勧めします。イントロからの簡単な引用は次のとおりです。

Luaは、すべてのグローバル変数を環境と呼ばれる通常のテーブルに保持します。...他の(実際には主な)利点は、このテーブルを他のテーブルと同じように操作できることです。このような操作を容易にするために、Luaは環境自体をグローバル変数_Gに格納します。(はい、_G._Gは_Gと同じです。)

はテーブルであるため、メタテーブルもあり、グローバル変数へのアクセスと作成を処理_Gするためのメタメソッドを定義できます。この例はセクション14.2にあります。この章全体を読んでください。それほど長くはありません(メタメソッドとメタテーブルに慣れていない場合は、第13章も参照してください。これはLuaが柔軟性の点で本当に優れているところです)。__index__newindex

ささいな方法と通常の方法について説明したので、スペクトルの行き過ぎた終わりを見てみましょう。例として、Unityのスクリプトへのアプローチを見ていきます。Unity javascriptは通常、変数、関数、および型を定義します。スクリプト自体がフレームごとに実行されるわけではないため、メソッドまたはタイプの範囲外で定義された変数はフレーム間で保持されます。代わりに、スクリプトに関数を定義させ、適切なタイミングで関数を呼び出します。したがって、フレームごとに何かを実行したい場合は、それをUpdate関数に入れます。Updateすべてのスクリプトは、独自のスコープを持っているため、独自の関数を定義できます。したがって、すべてのフレームで、スクリプトエンジンはすべてのオブジェクトを調べ、スクリプトのスコープにUpdateメソッドがあるかどうかを確認して呼び出します。

Luaに戻る-このようなソリューションでは、オブジェクト/スクリプト/ノードが何であれ、オブジェクトごとに個別の環境を作成する必要があります。次に、フレームごとにノードにアタッチされたスクリプトを実行する代わりに、メインループはすべてのノードを通過し、それらの環境内で関数を実行します。環境を切り替えることもできるので、実行する前にグローバル環境をノードのenvに設定し、完了したら元に戻すことができます。これにより、スクリプトは適切と思われるグローバルを使用し、フレーム間で永続化して、名前の衝突やグローバルな名前空間の汚染の可能性を排除できます。さらに、メタメソッドを使用して、ノードの環境を実際のグローバル環境内にネストしたり、ヘルパーメソッドを使用してAPI環境内にネストしたりできます(基本的に、__indexparent)。

于 2012-11-22T10:24:16.877 に答える