はじめてのミッションエディット 変数編 -ArmA訓練所-

ArmA訓練所
2007/07/02

目次


変数を覚えよう

ArmAではスクリプトコマンドを使ってエディターでは出来ないような様々なことが実現可能です。
スクリプトコマンドで複数のデータを扱う場合には変数を使います。
デスマッチやフラッグファイトミッションを作るなら必須だと思います。
ここではスクリプトで使う変数について説明します。

変数

変数とは、データを入れる箱であるとプログラミングの解説書には書いてあります。
早い話、データに名前を付けて中身がその都度変更されたりするものです。
X = 10を実行するとXは10という数値になり、Y = X - 5を実行するとYは5、Xは10ということになります。
このようなXやYのようなものが変数であり、使い方次第でとてもユニークなスクリプト処理を実現できます。

Local変数

ローカル変数は、その変数を定義したスクリプトでしか参照されません。
また、スクリプト中のブロック内で定義したローカル変数はそのブロック内でしか参照されません。
これは複数の巨大なスクリプトを作成する際に変数が予期せぬ箇所でデータを書き換えたりするのを防ぐために使われます。
スクリプトの結果がスクリプト内で完結するような場合の変数はこのローカル変数で問題ないと思います。
ローカル変数は変数名の先頭が必ずアンダースコアでなければなりません。
例えば_localvariableというような名前です。

他のスクリプトに変数を再利用してもらうような場合には次で説明するGlobal変数を使います。

Global変数

グローバル変数は変数宣言したコンピュータのどのスクリプトからも参照できます。
たとえばwestScoreというグローバル変数があった場合、スクリプトAがwestScoreに点数を加えたり、
スクリプトBがwestScoreを表示したり出来ます。
どのスクリプトも一つの変数に変更を加えることが出来るため、値の変更には注意する必要があります。
グローバル変数は先頭にアンダースコアを付けてはいけません。
その他のコマンド名などの予約語と同じ名前を付けないように気をつけましょう。

Public変数

ArmAでもっとも厄介なのがこのパブリック変数です。
Local変数とGlobal変数はそれぞれ、各自のコンピュータ上に存在します。
シングルプレイの場合はGlobal変数=Public変数ですが、マルチプレイの場合は少々厄介です。
マルチプレイで遊んでいる各プレイヤーのコンピュータ上では各自が変数を保持しています。
このため、ラグで非同期が発生したり、途中参加した場合に全員が持つ変数の値がずれたりします。
その結果CTFのスコアがずれるなどの問題が発生することがあります。
そのため、変数を一カ所(通常はサーバー)で管理し、その変数を各プレイヤーにネットワーク越しに配信する方法があります。
希ですが逆に各プレイヤーがローカルで持っている変数を全体に配信することもあります。
ネットワーク越しに配信するグローバル変数のことをパブリック変数と呼びます。
ネットワーク越しに配信する以外はグローバル変数と変わりありません。
変数をパブリックにするにはpublicVariableコマンドを使います。
publicVariableコマンドを使って値を配信した後、自動的に値が配信されることはないので、必要に応じて配信する必要があります。

変数の初期化

ArmAでは明示的な変数宣言が必要ありません。
これは利便性は高くなりますが、潜在的な問題を引き起こすことがあります。
具体的には変数に値が代入されるまで変数の値は不明となることです。
例えば次のような問題が有名です。

ループ開始
west得点条件待ち
westScore = westScore + 1;
ループ終端

これはスコアをカウントアップする処理で、常識的に考えるとwestScoreの値は
0,1,2,3,4・・・というように増えていくと考えがちです。
ところが、変数を初期化していないとwestScoreの値は初期状態では不明(そもそも数値なのか文字列、Booleanかすら不明)であるため、
westScore + 1(不明な変数 + 数値)の結果が不明となり、エラーとなってしまいます。
この問題を回避するためには、得点計算を始める前にwestScore = 0として初期化する必要があります。
また、Boolean値のOR条件を成立させる場合も同様です。

if ( destroyOBJ1 or destroyOBJ2 ) then { hint "good job!"; };

この場合のdestroyOBJ1とdestroyOBJ2のいずれかにtrueが入っていれば条件が成立すると考えがちですが、
この処理の前にそれぞれの変数がfalseで初期化されていないと、片方がtrueになってももう片方が不明であるため条件が成立しません。
その結果両方がtrueになった瞬間に両方がBoolean値になり、条件が実行される場合があります。
こうしたフラグやスコアの変数を用意する場合はinit.sqsかinit.sqfで変数を初期化しておくことを推奨します。
ローカル変数の場合はスクリプトの先頭付近で初期化しておきましょう。

変数の破棄

使用することは希ですが、変数を破棄することも出来ます。
たくさんの巨大な変数を使用するとメモリを多く消費し、ゲームの動作を遅くする可能性があります。
nilを使うことで変数を破棄し、メモリを解放します。

hugeVariable = nil;

よほど大量に、しかも巨大な変数を用意しない限りそこまでメモリを消費しないため、通常はこのような操作をする必要はありませんが、
変数を何十個、何百個と用意した場合は念頭に置いておくべきでしょう。


Homeへ