はじめに
この記事は、3DCG業界で働くArtist向けのMEL入門記事です。
普段の業務を効率化したいけど、MELの書き方が分からない、調べたけどイマイチ分からなかった、そんな方向けに書きました。
本記事は「変数を使う」をゴールとします。
環境
Autodesk Maya 2022.2
前回のあらすじと今回へのつなぎ
前回はsetAttr
とgetAttr
を使いました。
オブジェクトのアトリビュートを設定・取得できるようになったため、MELでできることとしてはかなりの範囲になります。
ここで一つsetAttr
とgetAttr
を生かして「二つのオブジェクトの位置を揃えるMEL」を書いてみましょう。
どうつくる?
仮に、CubeAとCubeBという二つのオブジェクトがあると仮定しましょう。
やりたいこととしては、「CubeBの位置をCubeAの位置に移動させる」としておきます。
アトリビュートを取得するコマンドと設定するコマンドはすでに知っているわけですから、
CubeAの位置をgetAttr
で取得して、その値をCubeBにsetAttr
で設定すれば実現できそうです。
実際のMELで書いてみましょう。
getAttr "CubeA.translateX";
getAttr "CubeA.translateY";
getAttr "CubeA.translateZ";
setAttr "CubeB.translateX" ?;
setAttr "CubeB.translateY" ?;
setAttr "CubeB.translateZ" ?;
あれ、setAttr
の一番後ろには「設定する値」が入るはずですが、
今回のMELを実現するためには、なにを入れてもよいかわかりません。
getAttr
で取得した値を入れたいところですが、どうすればいいのでしょうか?そんなコマンドがあったりするのでしょうか。
変数
コマンドではないですが、MELの機能として「変数」という機能があります。
変数とは読んで字のごとく「変わる数」です。
数というと数字をイメージするかも知れませんが、ここでは数字というよりは値というイメージのほうが近いです。
そしてMELの機能としての変数は、値を保存する箱のような機能を持ちます。
文法としては以下になります。
型名 $変数名
実際の書き方でいうとこのような感じです。
float $cubeATranslateX
型名は後述しますが、決まったものの中から選びます。コマンドと同様ですね。
変数名は、好きな名前を設定することができます。
「CubeAの移動X」を変数に入れるMELはこうなります。
float $cubeATranslateX = `getAttr "CubeA.translateX"`;
なにやら新要素がたくさんありますが、ひとまず実行してみましょう。
シーン上には忘れずにCubeAを配置してください。
できました、が、
特になんの変哲もありません。
ログには、
// 結果: 0 //
と表示されていますが、これは変数を書かないときでも同様です。
ですが、今回の実行では変数cubeATranslateX
に0が入りました。
いくら変数の中に0が入りましたと言われても、目で見ないとわからないですよね。
それでは下記のMELで確認してみましょう。
float $cubeATranslateX = `getAttr "CubeA.translateX"`;
setAttr "CubeB.translateX" $cubeATranslateX;
シーン上には原点にCubeAを、X座標を適当に移動させたCubeBを置いてください。
CubeBが原点に移動しましたね!
色々と分からない文法はたくさんありますが、変数cubeATranslateX
に値が入っていたのは間違いなさそうです。
細かい文法を見ていく
文法の説明をすっ飛ばしてしまいましたが、ひとつずつ確認していきましょう。
要素としては三つあり、それぞれ「代入」「式」「型」といいます。
代入とはなんぞや?
代入とは変数に値を入れることです。
float $cubeATranslateX = `getAttr "CubeA.translateX"`;
上記のMELは変数cubeATranslateX
にCubeAの移動Xの値
を代入するという処理です。
空っぽの箱に物が入れられるイメージですね。
変数に代入する際は、数学のように=(イコール)
を使いますが、右辺と左辺が逆になります。
代入したいものを右辺に置き、代入されるものを左辺に置きます。
間違えやすいので要注意です。
式とはなんぞや?
それ自体が値を返すものです。
別の言い方をすると「変数に代入できるもの」ですね。
float $cubeATranslateX = `getAttr "CubeA.translateX"`;
上記のMELでは「`getAttr "CubeA.translateX"`」が式になります。
返すというとピンとこないかも知れませんが、イメージとしてはgetAttr
コマンドがCubeAの移動Xを値を取ってきてくれて、その値を渡してくれる、というような感じです。プログラミングでは、このようなことを値を返すといいます。
渡してくれるので変数で受け取りが可能というわけです。
よく見ると見慣れない「`」がコマンドの両端についていますね。これもMELの文法の一つです。
コマンドを式として使用する際には「`(バッククォーテーション)」で両端を囲う必要があります。
これはルールだとしか言いようがないため、忘れないように注意しましょう。
ちなみにコマンドを「`」で囲ったものだけが式ではありません。返すことができればなんでも式です。例えば、
1 + 2
これは式です。
え、数学とそっくりじゃんと思いましたか?そうです。そっくりなのです。
+
を普通に使えることにも驚きかと思いますが、それは今回は置いておきます(これらは演算子と呼ばれるものです。また別の機会に解説します)
1 + 2
では3を返すことができますよね?ですので1 + 2
は式なのです。
float $result = 1 + 2;
上記では変数result
に3が代入されるということになります。
なんなら、+
等を使わなくても式としては成立します。
float $result = 10;
間話 変数に代入できるもの
冒頭で、変数はイメージとしては数字というよりも値に近いという話をしました。
数字以外の値とは具体的にはなにがあるでしょうか?
実はみなさんはすでに使ったことがあります。それは文字です。
(プログラミングではもっぱら文字列と呼ぶことが多いため、以下文字列と呼称します)
文字列をMELで表現する際には"(ダブルクォーテーション)
で両端を囲う必要があります。
float $text = "Hello";
こんな感じですね。
しかし、もう一点ルールがあるのです。
ためしに現状のスクリプトを実行してみましょう。
エラーは出ませんでしたが、警告されてしましました。
// 警告: Line 1.22 : 文字列 "Hello" を 0 の float 値に変換します。 //
// 結果: 0 //
なぜかはわかりませんが変数text
の中身が0に変換されてしまいました。
実はこれは変数の型が合っていないからなのです。
型とはなんぞや?
変数の文法をもう一度おさらいしましょう。
型名 $変数名
float $cubeATranslateX
上記でいう「float」というのがまさに型になります。
この型には種類があり、変数に入る値の種類を決定するものになります。
今回は重要なものを三つだけご紹介します。
float型
float型の変数に入る値は、浮動小数点です。
ここでは単に小数という認識で問題ありません。
float &pi = 3.14;
int型
int型の変数に入る値は、整数です。
int &cubeCount = 15;
小数を使用しない場合は、こちらを使うことになります。
floatでも代用可能ですが、整数であるべきときは必ずintを使いましょう。
たとえば、シーン上にあるCubeの数を変数に代入するときのことを考えます。
float型を使っている場合は、誤って1.5と入れてしまうこともできてしまいます。
さすがに問題ですよね。Cubeが1.5個あるといわれても、その後の処理を正しく実行できません。
string型
string型の変数に入る値は、文字列です。
string $cubeName = "CubeA";
先程も少し説明したように、文字列をMELで表現する際には"
で両端を囲う必要があります。忘れやすいので気をつけましょう。
string型を学んだところで、
float $text = "Hello";
先程、警告を出されたMELはどこを直せば良いでしょうか?
string $text = "Hello";
変数text
の型がfloatになってしまっていたので、string型に直せば文字列"Hello"
を代入することができますね。
二つのオブジェクトの位置を揃えるMEL リベンジ
さて変数について学んだところで、「二つのオブジェクトの位置を揃えるMEL」を書く準備が整いました。
実現したいこととしては「CubeBの位置をCubeAの位置に移動させる」です。
早速書き進めていきましょう。
まずはCubeAの位置をgetAttr
で取得しましょう。取得した値は変数にとっておきたいので、以下のようになります(コマンドを「`」で囲うのを忘れずに)
float $cubeATranslateX = `getAttr "CubeA.translateX"`;
float $cubeATranslateY = `getAttr "CubeA.translateY"`;
float $cubeATranslateZ = `getAttr "CubeA.translateZ"`;
これでそれぞれの変数に、3軸の座標が代入できました。
続いて、その値をCubeBにsetAttr
で設定していきましょう。
setAttr "CubeB.translateX" $cubeATranslateX;
setAttr "CubeB.translateY" $cubeATranslateY;
setAttr "CubeB.translateZ" $cubeATranslateZ;
あとは上記の二つを合体させるだけです。
float $cubeATranslateX = `getAttr "CubeA.translateX"`;
float $cubeATranslateY = `getAttr "CubeA.translateY"`;
float $cubeATranslateZ = `getAttr "CubeA.translateZ"`;
setAttr "CubeB.translateX" $cubeATranslateX;
setAttr "CubeB.translateY" $cubeATranslateY;
setAttr "CubeB.translateZ" $cubeATranslateZ;
これで動くはずです。
早速実行してみましょう!
やりました!大成功です!
型の記述
もしかしたらsetAttr
で「$cubeATranslateX」と書いてあるところで疑問に思った方がいるかもしれません。「型は書かなくてもいいの?」と。
実は型を記述するのは最初の一回のみというルールがあります。
最初に使う際に「float」と記述していれば、二回目以降は「float」と書かなくても良いのです(というより書いてはいけません)
【もっと知りたい】変数の宣言と初期化
今回は、
string $text = "Hello";
というようなかたちで変数を記述しましたが、この記述は初期化といいます。
初期化?言葉からは意味が想像し辛いですよね。
初期化の意味を知るには、まず変数の宣言を知る必要があります。
まず変数というのは、下記のような記述をすることができます。
string $text;
$text = "Hello";
上の行が宣言で、下の行が代入です。
宣言は文字通り、変数を使いますよという宣言です。変数の型と変数の名前を宣言し、以降の行でその変数が使用可能になります。
代入をしない限りは変数の中は空っぽのままです。
初期化というのは、変数の宣言と代入と同時に行うことをいいます。
string $text = "Hello";
宣言だけだと変数の中身は空っぽのままですが、同時に代入まで済ませてしまう...つまり初期値を設定しているわけです。
なので初期化と言うんですね。
基本的にシンプルなMELを書く分には、初期化で十分に書くことができます。
ですが、場合によっては宣言のみを先に行い、あとで代入することもありますので、頭の片隅に入れておくと良いかも知れません。
おわりに
いかがでしたか?
変数はほとんどのプログラミング言語に存在する、非常にスタンダードな機能です。
最初はとっつきにくかったり、どれがどれだか分からなくなるかも知れませんが、次第に慣れます。
最初のうちは一つ一つ確認しながらスクリプトを書いていきましょう。
次回はこちら→【ArtistでもMELが書きたい】Maya MEL入門(8)
参考