変数には「スコープ」と呼ばれるアトリビュートがあり、MAXScript コード内で変数がアクセス可能な場所を決定します。
MAXScript には、グローバルとローカルの 2 種類の変数スコープがあります。
「グローバル変数」は実行中のすべての MAXScript コードで見ることができ、3ds Max を終了するまで値を保持します。
「ローカル変数」は、現在有効な構文スコープ内のコードに対してのみ直接可視となり、現在のスコープが有効な場合に限り、値が保持されます。スコープが有効でなくなると、そのスコープにローカルの変数にアクセスできなくなります。これは、多くのプログラミング言語に実装されている変数の概念と同様です。次に、MAXScript が新しいスコープを作成する条件について説明します。
MAXScript では、明示的に宣言したり、グローバルとローカル変数の両方を初期化するために使用する言語構成が提供されています。
次に変数宣言( <variable_decls> )の構文を示します。
前述のように、ローカル変数はスコープが有効な限り値を保持します。ネストされているスコープでは、通常、これは非常に短時間です。関数、ループ式、またはブロック式の実行開始から実行終了までです。
スコープが実行範囲に入るたびに、ローカルの新規セットが作成され、スコープの終了時に削除されます。
変数を常に明示的に宣言することは推奨される方法です。その理由については、このページの以降の部分を参照してください。変数のスコープ
3ds Max 8 以降、MAXScript は変数名をグローバルとして明示的にアクセスする方法を提供しています。変数のグローバルのプール内に存在している場合に使用されます。変数がグローバル スコープ内に存在していない場合、明示的にグローバルなものとして作成されます。
構文はダブルコロンの'::'で、このトピックで記述されます。
状況によってはトップ レベルのスコープの有効期間を延長でき、トップ レベルで宣言されたローカルは値をその延長期間にわたって保持できます。
特に、スクリプト化されたロールアウト、ユーティリティ、プラグイン、スクリプト コントローラ、マクロ スクリプトで宣言されたトップ レベルのローカルは、ロールアウト、ユーティリティ、プラグイン、マクロ スクリプトが存在する限り値を保持します。
通常、これらのローカルは再定義されるまで存在し続けます。たとえば、マクロ スクリプトを定義して初めて実行するときトップ レベルのスコープが作成され、マクロ スクリプトを再定義しない限り、継続実行数を超えるまで有効になります。この時点で、既存のトップレベル スコープが破棄され、新しいスコープ(およびそのトップレベル ローカル)が作成されます。
これにより、これらの構文のトップ レベル ローカルをプライベート グローバルとして使用できます。保持される値は実行中はそのまま残りますが、構文内のコードのみが変数を参照するため、他のグローバルと競合することはありません。
スクリプト化されたプラグインでは、プラグインの代わりにトップレベル ローカル スコープの別のコピーが「個々に」作成されます。このスコープは、そのインスタンスが残っている間、現在の 3ds Max セッションが終了するまで有効です。
変数を明示的に宣言せず、その変数名が上のレベルのスコープに存在しない場合は、その変数を初めて使用するとき MAXScript によって変数が作成され、特別な値 undefined を保持するために変数が初期化されます。変数を使用する前に、変数を明示的に宣言したり値を初期化する必要はありません。前のステートメントで明示的に宣言されていない変数は、暗示宣言変数と呼ばれます。暗示的に宣言された変数のスコープは、変数が最初に使用されたときの MAXScript のスコープ コンテキストになります。MAXScript スコープ コンテキストの初期値はグローバルで、次の場合に新しいスコープ コンテキストが開かれます。
これらの新規スコープ内では、新しく参照された変数は、ローカル変数として明示的に宣言されます。
スコープ コンテキストはネストされています。明示的または暗示的に宣言された変数のスコープが 1 つのスコープ コンテキストのレベルになり、その下のレベルのスコープ コンテキストすべてに拡張されます。
上のスクリプトで、変数 a はグローバル スコープ コンテキストで最初に使用され、スコープにはスコープ コンテキスト グローバル、レベル 1、およびレベル 2 が含まれます。
変数 b は、スコープ コンテキスト レベル 1 で最初に使用されるのでローカル変数として明示的に宣言され、スコープにはレベル 1 とレベル 2 のスコープ コンテキストが含まれます。
変数 i および j はスコープ コンテキスト レベル 2 で最初に使用され、スコープはスコープ コンテキスト レベル 2 のみです。
変数 k のスコープは、このスクリプトが既に実行されたかどうかにより異なります。
初めてスクリプトを実行した場合、変数 k は最初に 5 行目で定義され、スコープはスコープ コンテキスト レベル 2 になります。
また、変数 k は 11 行目で再度使用されています。5 行目で定義された変数 k は、ここではスコープ内にないため、新しい変数 k が定義され、スコープはグローバルになります。
2 回目にスクリプトを実行する場合、5 行目で MAXScript により変数 k が既に存在することが検出され、既存の変数 k が使用されます。
このため、最初にスクリプトを実行すると、11 行目で undefined が出力されますが、2 回目にスクリプトを実行すると、11 行目では 5 行目で計算された最後の値が出力されます。
ローカル変数を明示的に宣言する場合、上のスコープ コンテキスト レベルで使用した変数と同じ名前を再使用できます。
この場合、新しく宣言したローカル変数は、同じ名前の外部変数を不可視にします。
ローカル変数のスコープ内でのこの変数名への参照は、以後この新しいローカル変数が使われます。
ローカル変数のスコープの最後に到達すると、次の外部変数が再び可視になります。
この可視手順は「構文スコープ」と呼ばれます。次のスクリプトに構文スコープの例を示します。
1 つの変数名を何度も使うことに違和感があるかもしれませんが、大型のプログラムの場合これらのスコーピング規則が便利な場合もあります。
たとえば、新しいユーザ インタフェース アイテムとそのハンドラをユーティリティ スクリプトに追加する場合、ハンドラに使用する変数をローカルとして明示的に宣言すると、これらの変数がスクリプト内のほかの場所で使用されている同名の変数に依存しないことが保証されます。
スクリプトを作成するときは、ローカル変数およびグローバル変数を明示的に宣言することをお勧めします。
暗示的な宣言は簡易的に提供されるものであり、通常、リスナーでインタラクティブに作業する場合や短いスクリプトを作成する場合に使用します。
長いスクリプトを作成する場合は、変数を明示的に宣言するとエラーが軽減し、コードが読みやすくなります。
また、特にグローバル変数が必要な場合を除き、すべての変数をローカルとして宣言することをお勧めします。これは、次のような理由によります。
ブロックまたは関数で使用するすべての変数名をひとまとめにできるため、変数名を見つけるのが簡単で、スクリプト内で誤った名前の使用を防ぐことができます。
同時に複数のスクリプトを実行する場合(たとえば、スクリプト ユーティリティを実行し、シーン内にスクリプト コントローラがある場合)、両方のスクリプトで同じグローバル変数名が使用されているとスクリプト同士が干渉し、両方のスクリプトで同じグローバル変数名が使用されているとスクリプト同士が干渉し、一方または両方のスクリプトで予期できないエラーが発生する場合があります。
上のレベルのスコープで同じ名前の変数が既に宣言されている場合でも、確実に正しい変数を使用でき、上のレベルの変数の値を無意識に変更することはありません。
3ds Max R2.5 では、3ds Max クラス、MAXScript メソッド、または MAXScript 読み込み専用グローバル変数が暗示宣言ローカル変数と同じ名前を持ち、その変数名への代入が発生した場合には、MAXScript ランタイム エラーが生成されます。変数名が既にグローバル スコープに存在していたため、暗示宣言ローカル変数は作成されません。ユーザがロードしたサード パーティのプラグインによって 1 つ以上の新規 3ds Max クラスが作成されるため、変数名がグローバル変数名の場合は前もってこれを知ることができません。3ds Max R3 では、これらの変数への最初の参照が代入であることが MAXScript コンパイラにより検出されると、読み込み専用のシステム グローバルへの参照としてそのままにするのではなく、暗示的にローカル変数が宣言されます。たとえば、3ds Max R2.5 で次の式を実行すると、値は Box になります。これは、 Box が 3ds Max オブジェクト クラスだからです。3ds Max R3 では、変数 box の最初の使用が代入であることが MAXScript により検出され、暗示宣言ローカル変数 box が作成されます。3ds Max R3 でのこの式の結果は、 undefined です。
次のスクリプトでは、定義されていない変数 k を 7 行目で使用することにより、エラーが挿入されています。出力では、エラー コール スタックのトレースバックにより、関数 afunc 内と、 afunc を呼び出しているブロック式での変数 b の値が表示されます。
3 行目と 12 行目を削除してこのスクリプトを実行すると、出力結果は次のようになります。関数 afunc とブロック式は別の MAXScript スコープ コンテキストに存在するため、変数 b はそれぞれローカルとして暗示的に宣言され、異なる値を持ちます。ただし、これらは暗示的に定義されるため、エラー コールスタック トレースバックには表示されません。