MAXScript の変数について

# 概要
- 「変数」について説明します。

# 難易度
- 入門

# 閲覧想定ユーザー
- 3dsMaxの操作をある程度行えるデザイナー
- これからMAXScriptを始める方
- プログラミング経験がゼロの方

# 想定所要時間
- 60分

# 要点
変数を知るために、2つの要点をおさえましょう。

- **箱のように値を出し入れできる**
- **名前を付けないと利用できない**


# 箱のように値を出し入れできる
1つ目の要点です。
**変数は「箱」のように「値」を出し入れできます。**

### 箱
- 実際に箱型の3Dオブジェクトが存在している訳ではなく、プログラムで処理をするための、疑似的な箱です。 

### 値
- 出し入れできる**「値」**とは、数値や文字列、オブジェクトなどです。

理解を深めるために、以下のコードを見てみましょう。

```
x = 1
```

この数式を左から、順を追って説明していくと、以下の処理が走っていることになります。


### 処理１
![変数1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144790/499fe373-c0f5-6f03-3d55-4582f288fd2e.png)

プログラムは上から順に1行ずつ、左から右に処理がされます。
まず、このプログラム内に `x` という名前の**変数**を生み出しています。
この段階では「 `x` という空箱が用意された」と考えてください。

### 処理２
![変数2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144790/ad44cc70-43d5-de0a-3c4b-9c8240f5aac4.png)

続いて、 **箱**（x）に**値**（1）を入れています。
この時点で、`x` という箱に `1` という値が入ったことになります。

---

### 例

理解を深めるために、次のコードを実行して箱の中身をのぞいてみましょう。

```
x = 1
print x
```

2行目で `print x` としています。

**`print` というのは、スペースを空けた先に書かれている内容を、MAXScript リスナーに文字として表示させる命令です。**
この `print` は、スクリプトの開発中に変数の中身などを知るために用います。

このコードは `print` からスペースを空けた先に `x` を記載しているため**「変数 x の内容を表示する」**といった処理が走ることになります。

--- 

3dsMaxでスクリプトを実行すると、Maxスクリプトリスナーに `1` が表示されます。実際に確認してみましょう。

▼ MAXScript リスナーは、メニューバーの「スクリプト」→「MAXScript リスナー」を選択すると表示できます。
![cdb5bff6-f991-4e38-8d57-48e74d57022a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144790/c6574e7c-0fbd-e75f-0659-19aaaedd22a0.png)


▼ MAXScript リスナー ウィンドウです。
![2a2d6d97-4ae4-43bd-8950-be4f0a8f101d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144790/42f831bf-2ab0-4947-59c3-f5c84e1dd150.png)


※3dsMaxの環境によっては、最初から他のテキストが表示されている場合もあります。その場合は、一度ログを消去してから、新しくスクリプトを実行してください。

# 名前を付けないと利用できない
2つ目の要点です。
**変数を使うためには、その変数の名前を知っている必要があります。**
理由は単純で、値を出し入れするためのコードを書けないからです。

※単に `1` や `2` などの「数値」を扱うだけなら、直接その数値を書くだけです。

# 変数を使うメリット
名前を付けないと使えない変数、使うのが面倒に感じたかもしれません。
**しかし、変数は同じ値を何度も使いまわす場合に便利です。**

たとえば、**同じ明るさを持つライトを複数作成する**ツールを作るとします。

```
Omnilight multiplier:1 pos:[0,0,0]
Omnilight multiplier:1 pos:[10,0,0]
Omnilight multiplier:1 pos:[20,0,0]
Omnilight multiplier:1 pos:[30,0,0]
Omnilight multiplier:1 pos:[40,0,0]
Omnilight multiplier:1 pos:[50,0,0]
Omnilight multiplier:1 pos:[60,0,0]
Omnilight multiplier:1 pos:[70,0,0]
Omnilight multiplier:1 pos:[80,0,0]
Omnilight multiplier:1 pos:[90,0,0]
Omnilight multiplier:1 pos:[100,0,0]
```

`multiplier:1` の `1` が強度を示しています。
強度を変更する場合、`multiuplier` の値を1行ずつ変えなければいけません。
これだと、修正するのが大変手間です。

そこで**変数**を使うと、明るさの値を一気に修正することができます。

```
x = 1
Omnilight multiplier:x pos:[0,0,0]
Omnilight multiplier:x pos:[10,0,0]
Omnilight multiplier:x pos:[20,0,0]
Omnilight multiplier:x pos:[30,0,0]
Omnilight multiplier:x pos:[40,0,0]
Omnilight multiplier:x pos:[50,0,0]
Omnilight multiplier:x pos:[60,0,0]
Omnilight multiplier:x pos:[70,0,0]
Omnilight multiplier:x pos:[80,0,0]
Omnilight multiplier:x pos:[90,0,0]
Omnilight multiplier:x pos:[100,0,0]
```

このようなコードになります。
こうすれば **変数** `x` の値を変えるだけで、生成されるライトの強度も変えることができます。

### 実践
以下スクリプトの**変数** `x` の値を書き換えて、3dsMaxでスクリプトを起動して変化を確認してください。
※編集したスクリプトを起動する前に、生成されたライトを削除してください。同じ位置に生成されるので、判別が付かなくなります。

```
x = 1
Omnilight multiplier:x pos:[0,0,0]
Omnilight multiplier:x pos:[10,0,0]
Omnilight multiplier:x pos:[20,0,0]
```

# 計算にも使える
**変数は計算式に用いることができます。**

以下のスクリプトを実行すると、MAXScriptリスナーに `10` が表示されるはずです。

```
x = 2
y = 5
z = x * y
print z
```

### 実践
以下スクリプトの変数 `x` `y` の値を書き換えて、3dsMaxでスクリプトを起動して `z` の値が変化することを確認してください。

```
x = 2
y = 5
z = x * y
print z
```

# 変数の中身は上書きできる
**変数は、後から入れた値によって中身を上書きすることが可能です。**

### 例
以下のスクリプトを実行すると、MAXScriptリスナーに `100` が表示されるはずです。

```
x = 1
x = 100
print x
```

しかし、同時にこれはリスクでもあります。
複雑なコードになってくると、誤って中身を上書きしてしまい、意図しない値が返ってくる場合もあるからです。

# 中身の何も入ってない変数

MAXScriptでは、コード内に変数を呼び出した時点で、プログラム内に変数が存在する扱いとなります。
したがって、先に値を入れていなくても、変数自体を呼び出せてしまいます。

### 例

それを確かめるために3dsMaxを再起動してから、この1行だけのコードを実行してみてください。
**（正しく実行させるためには、必ず3dsMaxを再起動してからスクリプトを実行してください）**

```
print x
```

`undefined` という値が MAXScriptリスナーに表示されるはずです。

この `undefined` というのは**「変数 x の中身を表示しようとしたが、中身に何も入っていませんよ」**という結果を表しています。
もうちょっと厳密に書くと、**未定義状態** を意味します。

先程までは、変数を `print` で表示させる前に、かならず値を入れてました。
しかし、先に何かを入れないと **未定義状態** になってしまい、正しい計算が行われません。

--- 

### 例

未定義の変数について理解を深めるために、以下のスクリプトを起動してみましょう。

```
x = 1
z = x + y
print z
```

エラーで処理が止まって、以下のようなダイアログが表示されるはずです。
![affe47a2-04c2-48b4-8efe-c185e46d008c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144790/85651c9e-221a-3beb-08db-22149e237734.png)


これは、**値** `1` が入った **変数** `x` に、**未定義の変数** `y` を足そうとして、**3dsMaxが上手く計算できずに発生したエラーです。**

書いているコードが複雑になってくると、このようなエラーも発生しやすくなります。
**意図せず未定義の変数を計算させないように、注意しましょう。**

※なぜエラーになるのか、エラー部分の特定方法などは別の記事で解説します。

# 参考
- https://wa3.i-3-i.info/word1603.html
- https://kitsune.blog/variable
- https://qiita.com/chousensha01/items/b046ff51688059516ab9