過去2回のセミナーの再配信が終了しました。
ご視聴いただいたみなさま、大変ありがとうございました!
引き続きMaya Pythonを学習される方にとって役立つ情報を発信していきますので
今後ともどうぞよろしくお願いいたします。

ツール作成の全体フローを最短距離で体験できます。スクリプト未経験の方におすすめ!
https://tutorials.cgworld.jp/set/2050

Mayaのオペレーションの自動化について徹底解説。様々な操作を自動化できるようになります
https://tutorials.cgworld.jp/set/2041
こんにちは!ビーバー@ゲーム業界歴約20年 です。maya python初心者の方のために、カンタン・わかりやすい解説サイトを作っています。
maya pythonの学習情報って少ないですよね。自分が骨を折った経験をもとに、maya python基礎を最速で習得できる10回のチュートリアルを作ってみたので参考にしていただければ幸いです。
今回は、8回目。手作業でやると時間がかかってしまう「らせん状の配置」について、スクリプトから一発で行う方法を紹介します。スクリプトは一度書くと、何度でも使えるのでとても便利ですよ!

※当サイトで紹介する商品は、アフィリエイトプログラムを利用しています。
コーンをらせん状に配置して、先端をlocatorに向ける
画像のようなシーンを使って進めていきます。
- 原点にlocator1
- その子供にpCone1
- Y=20にlocator2 を配置

このシーンでコーンをらせん状に配置し、コーンの先端がY=20のlocator2を向くようにします。
下記のスクリプトを実行。
cone = "pCone1"
for i in range(15):
cmds.setAttr("locator1.ry",i*45)
cone2 = cmds.duplicate(cone)
cmds.parent(cone2,w=True)
cone2 = cone2[0]
cmds.setAttr(cone2+".ty",i*1)
meshes = cmds.ls(type="mesh")
conetranses = cmds.listRelatives(meshes,allParents=True)
for trans in conetranses:
aimcon = cmds.aimConstraint("locator2",trans,offset=(0,0,-90))
cmds.delete(aimcon)


おお~!一発でらせん状に配置された!

今回はちょっとスクリプトが長いね。解説に入る前に、
どのようなアプローチでコーンのらせん状配置を実現するか考えてみよう
解説
何かのモデルやモーションを作る時と同じで、
最初にどのような作り方をするか段取りを考えたうえで、スクリプトを書いていきます。
今回は以下のような段取りにしました。
コーンを原点にあるlocator1の子供にする
- locator1を45度回転
- コーンをduplicate、ペアレント解除
- コーンの位置を上へずらす(処理がすすむにつれ、より高い位置にずらしていく)
- この処理を繰り返す
最後に、コーンをまとめてlocator2に aimコンストレインする
これらを12行のスクリプトにしています。
スクリプトの構造
スクリプトの挙動を1行ずつ確認していきましょう。
行数 | スクリプト | 処理内容 |
1行目 | cone = “pCone1” | pCone1を変数coneに代入 |
2行目 | for i in range(15): | 以下の処理を15回繰り返す。 iには0~14が入る |
3行目 | ␣␣␣␣cmds.setAttr(“locator1.ry”,i*45) | locator のtyの値にi*45を代入 |
4行目 | ␣␣␣␣cone2 = cmds.duplicate(cone) | pCone1を複製してcone2に代入 |
5行目 | ␣␣␣␣cmds.parent(cone2,w=True) | cone2のペアレントを解除 |
6行目 | ␣␣␣␣cone2 = cone2[0] | cone2がリスト型になっているので 要素を取り出してcone2に代入 |
7行目 | ␣␣␣␣cmds.setAttr(cone2+”.ty”,i*1) | cone2のtyの値にi*1を代入 |
8行目 | meshes = cmds.ls(type=”mesh”) | メッシュを取得してmeshesに代入 |
9行目 | conetranses = cmds.listRelatives(meshes,allParents=True) | meshesの親のtransformノードを取得、 conetransesに代入 |
10行目 | for trans in conetranses: | conetransesの要素に対して以下を実行 |
11行目 | ␣␣␣␣aimcon = cmds.aimConstraint(“locator2”,trans,offset=(0,0,-90)) | locator2の方向に向くように aimコンストレインを実行 |
12行目 | ␣␣␣␣cmds.delete(aimcon) | コンストレインノードを削除 |

それでは詳しく処理を見ていこう!
4行目:pCone1を複製してcone2に代入

オッケ~!じゃあ質問です。
4行目は複製したコーンをcone2に代入しています、どうしてでしょう?
行数 | スクリプト | 処理内容 |
4行目 | cone2 = cmds.duplicate(cone) | pCone1を複製してcone2に代入 |

5行目以降でcone2に対して処理するから、、かな?

そうだね。4行目はfor文に入っていて、繰り返される処理なんだ。
pCone1は、合計15回duplicateされて、
複製されたコーンの名前は「pCone2~16」になるから、
名前が変わっても、以降の処理に対応できるように変数にしておくんだよ。
5行目:cone2のペアレントを解除
ここではcone2をペアレント解除して、ワールド直下にしています。
行数 | スクリプト | 処理内容 |
5行目 | cmds.parent(cone2,w=True) | cone2のペアレントを解除 |
初出のコマンド parent() について見ていきましょう。
parent
その名の通り、ノード同士の親子付けを行うコマンドです。
()内の書き方を解説します。
cmds.parent(“子供にしたいオブジェクト”、”親になるオブジェクト”、フラグ=〇〇)

フラグ「w」は「world」の省略版、ワールドにペアレント化するフラグだよ。
6行目:リストの要素を取り出してcone2に代入
行数 | スクリプト | 処理内容 |
6行目 | cone2 = cone2[0] | cone2がリスト型になっているので 要素を取り出して改めてcone2に代入 |
ここではcone2[0]とすることで、リストから要素を取り出しています。

リストからの要素取り出しは、たしか5限目でやったなあ。。
ここはcone2のままじゃダメなの?

次の行でsetAttrを実行したいけど、
cone2はリスト型になってしまっているから、そのままでは実行できないんだよ。

次の行で処理ができるように、リストからあらかじめ取り出しておくんだね。
cone2の中身を確認してみましょう。
最初のシーンに対して、スクリプトの3~5行目のみを実行し、cone2をハイライト+実行します。


赤枠で示したように、[‘pCone2’]が返ってきました。[ ]に入っているので、リスト型になります。
cone2 = cone2[0] を実行してから、もう一度cone2を実行すると、、

pCone2 と、[ ]が外れ、リストの中の要素を取り出すことができました。
次の行からは、この単体の要素に対して処理を行っていくのです。


7行目:cone2のtyの値にi*1を代入
行数 | スクリプト | 処理内容 |
7行目 | cmds.setAttr(cone2+”.ty”,i*1) | cone2のtyの値にi*1を代入 |

さっきのリストから取り出したコーンのtyに、setAttrで値を設定しているね。
ここも内容的には問題ないよ!

だいぶ慣れてきたね!
ちなみにここまでが2行目のfor文の処理だ。
for文で行っている処理はこの通りです。
- locator1を45度ずつ回転
- コーンをduplicate、ペアレント解除
- コーンの位置を上へずらす(処理がすすむにつれ、より高い位置にずらしていく)
- この処理を繰り返す
次の行からが、コーンをまとめてlocator2にaimコンストレインする処理になります。
8行目:メッシュを取得してmeshesに代入
行数 | スクリプト | 処理内容 |
8行目 | meshes = cmds.ls(type=”mesh”) | メッシュを取得してmeshesに代入 |
ここではコーンを取得するために、typeフラグでメッシュのノードをシーンから探して、
変数meshesに代入しています。

lsコマンドのフラグの書き方はわかるんだけど、
mesh、みたいなノードのタイプ名ってどうやって調べるの?

lsコマンドのshowTypeフラグで調べることができるよ。
タイプ名の調べ方
cmds.ls(type=”○○”)のタイプ名(文字列)は、
lsコマンドのshowTypeフラグで調べることができます。
例えば、シーンのpCone2を選択して、下記のスクリプトを実行
print(cmds.ls(selection=True,showType=True))

赤枠のように、[ノード名 , タイプ名] が返ってきます。
9行目:コーンのtransformノードを取得、conetransesに代入
行数 | スクリプト | 処理内容 |
9行目 | conetranses = cmds.listRelatives(meshes,allParents=True) | meshesの親のtransformノードを取得、 conetransesに代入 |
meshesの中身はshapeノードのため、
その親のtransformノードを取得して変数conetransesに入れています。

親のtransformノードを取得しているのは、あとでaimコンストレインをかけたいからだね
親を取得するコマンドがlistRelativesかな?

そのとおり!
listReratives()
このコマンドでは、ノードの親や子を返してくれます。
cmds.listReratives(“ノード名”,フラグ=〇〇)
「allParents」フラグは親を返すフラグです。
10行目:aimコンストレインを実行
行数 | スクリプト | 処理内容 |
10行目 | for trans in conetranses: | conetransesの要素に対して以下を実行 |

10行目は
listRerativesで取得した、複数のtransformノードに対して処理を行う、だね!

10行目も大丈夫だね。じゃあ11行目行ってみよう!
11行目:aimコンストレインを実行
行数 | スクリプト | 処理内容 |
11行目 | aimcon = cmds.aimConstraint(“locator2”,trans,offset=(0,0,-90)) | locator2の方向に向くように aimコンストレインを実行 |
ここでは、conetranses のうちの一つの要素である trans
(中身はpCone*のトランスフォームノード)がlocator2の方向を向くように、
オフセット値を入れてaimコンストレインをかけています。

コマンドの名前はaimConstraint()、これは分かりやすいなあ
aimConstraint()
コマンド名の通り、エイムコンストレインを行うコマンドです。
cmds.listReratives(“コンストレインする側ノード名” , “される側ノード名” , フラグ=〇〇)
フラグはoffsetを指定しています。
フラグの書き方をヘルプで探すと、、引数タイプが[float, float, float]
これはどのように書けばよいのでしょうか?


これはGUIからオプション設定するときの書き方と同じと考えると簡単だよ


そうか、赤枠のオフセット値と同じように書けばいいんだね!
あと、11行目では「コンストレイン実行」をaimconという変数に入れています。
aimcon = cmds.aimConstraint("locator2",trans,offset=(0,0,-90))
これはすなわち、コンストレインノードが「aimcon」に代入されているのです。


コンストレインノードはこれだね!
12行目:コンストレインノードを削除
行数 | スクリプト | 処理内容 |
12行目 | cmds.delete(aimcon) | コンストレインノードを削除 |
「11行目で作成したコンストレインノード」を削除しています。
実行

それではドキドキの瞬間!スクリプトを実行しよう!
cone = "pCone1"
for i in range(15):
cmds.setAttr("locator1.ry",i*45)
cone2 = cmds.duplicate(cone)
cmds.parent(cone2,w=True)
cone2 = cone2[0]
cmds.setAttr(cone2+".ty",i*1)
meshes = cmds.ls(type="mesh")
conetranses = cmds.listRelatives(meshes,allParents=True)
for trans in conetranses:
aimcon = cmds.aimConstraint("locator2",trans,offset=(0,0,-90))
cmds.delete(aimcon)


できたよー!スクリプトの中身もちゃんとわかったよ!
まとめ
今回学習した内容のポイントをまとめます。
- setAttr,Duplicate,parentなどを組み合わせて、オブジェクトを規則的に配置する
- リストから要素を抜き出して処理する
- ノードタイプは lsコマンドの showTypeフラグで調べることができる
- listRelativesコマンドを使って、親ノードを取得する
- aimConstraintコマンドで、方向コンストレインを設定する

ここまで勉強してきたことを組み合わせてみたよ!
次回は、作成したスクリプトをファイルに保存して、別のシーンから使ってみる、
という内容を解説します。お楽しみに!
はじめてプログラミングを勉強するとき、エラーはつきものですよね。
何時間もスクリプトが動かないこともしばしば。。
そんな時、くわしい人に教えてもらいたい、と思うことはありませんか?
侍テラコヤは、はじめてpythonを学習する方にピッタリのサービスです。
サブスク型オンラインスクールで、月¥2980~の良心的なお値段!
現役エンジニアのサポートが充実しており、
オンラインのマンツーマンレッスンとQ&A掲示板で即座に悩みを解決することができます。
本サイトの【まとめ】 maya python 基礎 入門!では、
10回シリーズでmaya pythonの基礎が習得できるコンテンツを発信しています。
- ちまたのスクリプトを読んで、内容を理解したい
- mayaのスクリプトリファレンスの読み方を習得したい
- 自分で簡単なツールを書きたい
- 基礎的なmayaコマンドをpythonで使えるようになりたい
など、mayaでpython基礎を身に着けたい方は、ぜひご活用ください♪
オススメの本。pythonが楽しく学べます☆


復習はこちら↓
コメント