チュートリアル / 読んで触ってよくわかる!Mayaを使いこなす為のAtoZ
第106回:キャラクタのチェックツールを作ってみよう!
- Maya
- キャラクター・リグ
- ゲーム
- コラム
- スクリプト・API
- チュートリアル
- 初心者・学生
ホグワーツに入学希望の方、こちらにお集まりください!
もう一年以上前になりますがYouTubeにゲーム、ホグワーツ・レガシーのメイキング動画が上がっています。
「HOGWARTS LEGACY: Harry Potter │ Behind the Magic of Avalanche´s Masterpiece」
MayaやMotionBuilderを使用しているところもありまして、沢山のインハウスツールが登場します。
見ていて「うまソゲじゃないか!」というツールがありましたので今回ご紹介いたします。
キャラクタのセットアップを実行する前に、データに問題がないかチェックするツールです。
(応用すれば背景制作とか、いろいろなところでのチェッカーに出来ます。)
キャラクタとは、つまり「ジョイント」「スキニング」「メッシュ」などのことです。
それぞれに沢山アトリビュートがありますし、作り方によっては問題になる可能性もあります。不用意にジョイントにスケールが入ってしまっていたとか。
目視でチェックするのは大変で、ヒューマンエラーが起こりやすい部分です。
しかもチェック作業は全く何も楽しくない!
というわけで私がゲーム制作をしていたときも自作していましたし、おそらく多くのプロダクションでご用意していることでしょう。
でもそういうプロダクション以外では用意していないこともあるのでは?とおもったわけです。
一般的なチェック項目だけでなく、そのプロジェクトや会社独自のチェック項目もあるでしょう。
カスタマイズが必要になるツールでもあります。TAが勉強がてら作るのにもちょうど良いですし。
作りはじめは簡単なのですが、チェック項目を増やすとちょっとややこしくなるのがチェックツール。
順に作り方を見ていきましょう!
まずは一つだけチェックをしてみよう!
チェックツールというのは、多かれ少なかれ結局のところ「一つの項目をチェックする」機能を繰り返すことになります。
始めは一つだけチェックを行う機能を作ってみましょう。
ここではジョイントのSegment Scale Compensateのアトリビュートが無効になっているかどうかチェックしてみます。
Attribute Editorではこちらに表示されます。
そもそもSegment Scale Compensateが何かということですが、
有効になっていると「親のスケールの影響を打ち消して、自分の大きさを保つ補正」を行います。直訳すれば「部分スケール補正」。
下の図のように、OFFになっていれば親のスケールがそのまま反映されます。
通常のオブジェクトと同じ振る舞いになる、というわけです。
ONになっていれば自分の大きさを保つように、内部的にスケールを加えて補正しています。
問題なのは、このスケール処理はMaya独自といいますか、特殊な対応となります。他のDCCソフトでは再現される約束がありません。
ゲームに使おうとするとSegment Scale Compensateの処理は無視されて表示される可能性があります。
つまりゲームのデータとしてはちょっとトラブルになりがちなのです。ONにしたのにゲーム中ではOFFのような大きさで表示されたりするかもしれません。
リグを作る、ゲーム用に書き出す前には、Segment Scale Compensateが全て無効になっていることを確認したいわけです。
で、コードですが、一つのチェックならごくごく簡単です。
今日はPythonで。次のPythonスクリプトではSegment Scale Compensateが「ON」になっているものを見つけます。
チェックする場合は、正常なものを見つけるのではなく、異常なものを見つけるようにすることが多いです。
import maya.cmds as cmds
# Segment Scale Compensateが有効のジョイントを見つける。
joints = cmds.ls(type='joint')
invalidJoints = []
for joint in joints:
v = cmds.getAttr(f'{joint}.segmentScaleCompensate')
if v:
invalidJoints.append(joint)
if len(invalidJoints):
cmds.warning(f'Segment Scale Compensateが有効になっています: {invalidJoints}')
else:
print('Segment Scale Compensateは全てオフになっています。')
実行して、問題点が見つかるとこんな感じで出力されます。
# Warning: Segment Scale Compensateが有効になっています: ['joint4|joint2', 'joint4|joint2|joint3', 'joint4']
あとはこれを他のチェック項目も同様に、似たように繰り返すだけです。
問題点の報告の仕方として、文字列だけでは見づらいので、個数も表示したり対象ノードを選択したりと、工夫も色々必要です。
GUIと連動させる
ウインドウを作って、ボタンを押すとチェックが出来るようにしてみましょう。
ボタンから実行するために、先程のコードは関数にまとめておきます。
チェックを実行すると、問題があればボタンを赤色にします。大丈夫なら明るい緑にします。
コードはこんな感じになります。
import maya.cmds as cmds
from functools import partial
def checkSegmentScaleCompensate(*args):
# Segment Scale Compensateが有効のジョイントを見つける。
joints = cmds.ls(type='joint')
invalidJoints = []
for joint in joints:
v = cmds.getAttr(f'{joint}.segmentScaleCompensate')
if v:
invalidJoints.append(joint)
color = (0.7, 0.9, 0.1) # とりあえずOKの色で初期化
if len(invalidJoints):
cmds.warning(f'Segment Scale Compensateが有効になっています: {invalidJoints}')
color = (0.9, 0.1, 0.1) # NGの場合の色
else:
print('Segment Scale Compensateは全てオフになっています。')
# ボタンの色を変えます。argsの1つ目にボタンの名前が入っています。
cmds.button(args[0], e=True, bgc=color)
# ウインドウを作ります。
cmds.window(t='Character Checker', w=300, h=100)
# 上から下にレイアウトするためにcolumnLayoutにします。
cmds.columnLayout()
# rowLayoutで横並びでGUIを作っていきます。
# 左に置くボタンは隙間を作りたいのでcolumnAttachで少し左からオフセットさせます
cmds.rowLayout(nc=1, cw1=200, columnAttach=(1, 'left', 90))
# 左からの順番でGUIを作成。
btn = cmds.button(l='Run', w=120)
cmds.setParent('..')
# 改めて、ボタンのコマンドを設定します。
# 関数にボタンのGUI名をわたして、色替えなどに使わせます。
# functoolsモジュールからインポートしておいたpartialをコマンドに使います。(実行したい関数, 引数)を指定します。
cmd = partial(checkSegmentScaleCompensate, btn)
cmds.button(btn, e=True, c=cmd)
# ウインドウを表示します。
cmds.showWindow()
これで基本形は出来上がりました!
後は同じようなチェック処理を繰り返すだけ!とおもってしまうのですが、いやいや、案外そこがややこしいのです。
ベタに上の処理を増やしていくことも出来ます。
でもジョイントのチェックをするのに、各チェック用の関数で同じようにジョイントをlsで取るようなコードを実行するのもなあ、となるわけです。
同じようなことを繰り返すには、共通する処理をまとめたほうがあとで管理や増減が簡単になります。
そのための仕組みを考えてみましょう。
何が課題になりそうか?
この後課題となりそうな部分を具体的にあげてみましょう。
・チェック処理が10種類に増えたときも対応しやすいか?
今のコードでは、ウインドウの作成でrowLayoutとbuttonでボタンの部分を作っています。
これを10回ベタ書きすると読みにくくなると予想できます。
代わりにforループで好きなだけ追加出来る仕組みにしたい。でもどうやるのか?
・チェック機能を増やすときに対応しやすいか?
自動で問題箇所を修正する機能も欲しいとなったら、「自動修正+チェック」「チェックのみ」などいくつかの実行パターンが出てきます。
修正ありなしでチェック用の関数を増やすと、どんどん関数が増えてしまいます。
関数の引数にcheckSegmentScaleCompensate(autoFix)のように、自動修正するかどうか指示できれば、関数を増やさずに済みそうです。
・ツールを引き継いだ後に他の人でもわかるか?自分自身も後で見てわかりやすいか?
今のコードは規模が小さいので、コメントだけで十分仕組みがわかります。
もっとチェック項目や機能を増やすと、段々と読みにくくなっていきます。
特にあとで誰かが「チェック項目を増やしたい」「チェックの内容を修正したい」ときに正確に、不具合を誘発せず、しかも素早く対応出来るとベストです。
などなど、コードの書き方の工夫や、Pythonの機能をうまく使えば効果的なコードがかけますが、課題も多いものです。
いろいろ対応したサンプル
全て説明するとむしろ話がややこしくなりますので、下記画像のツールのサンプルをご用意しました。
ダウンロードしていただき、中身を丸ごとコピペしてScript Editorで実行すればウインドウが立ち上がります。
細かい説明はコード内に書いていますのでそちらをご覧ください。
急に色々追加されているコードのためちょっと複雑ですが、基本はこれまでの紹介内容と同じですので、順に読んでいけば大丈夫だと思います…。
簡単に説明しておくと、次の流れで実行しています。
・characterCheckerという関数でウインドウを作ります。
・testsという配列に、テスト項目の「説明書き」と「チェックを実行する関数」を記載します。これをもとにボタンなどを作ります。
・ボタンを押すとrunCheckerという関数が実行されます。引数には「チェックを実行する関数」「ボタン名(色替えのため)」「チェックボックス(自動修正するかどうか確認するため)」が含まれています。
・Run Allボタンを押すと、各ボタンに割り当てたコマンドと同じものをすべて実行します。
Run Allボタンにコマンドを渡すあたりとか、Pythonらしい感じもしますが、個人的には何が起きているかすぐに理解出来ずとてもイヤなのですが、まあ。
まとめ
コラムで取り上げるスクリプトやツールの話の範囲が狭ければサンプルも数行で済みますが、ちょっとコード量が多いものも登場させたかったので、今回のように「後はスクリプトを見てください!」式になりました。
それはそれで、文章で読むよりもコードとコメントを読んだほうがわかりやすい場合も多いですし。
みなさんもどんどんMayaをカスタマイズして好みのツールに仕上げていってみてください!