ある文字列を含む名前全てを検索したいときなどに「*」アスタリスクを用いることがあります。
例えば、「BCD*」と検索をする場合、以下のような結果になります。
「ABCD」、「BCDE」、「ABCDE」、「BCDEF」、「CDEF」、
Maya関数lsを用います。
#-*- encoding: utf-8
import maya.cmds as cmds
#オブジェクトを作成
cmds.polySphere(n = 'A_pSphere')
cmds.polySphere(n = 'B_pSphere')
cmds.polySphere(n = 'C_pSphere_hoge')
cmds.polyCube(n = 'pCube')
#検索
result = cmds.ls('*pSphere')
print(result)上記コードの実行結果は以下の通りです。
[u'A_pSphere', u'B_pSphere']ls関数の引数群の中にオブジェクトタイプ等を指定するものがあります。
#-*- encoding: utf-8
import maya.cmds as cmds
#オブジェクトを作成
cmds.polySphere(n = 'pSphere_mesh')
cmds.joint( p=(0, 0, 0) ,n = 'pSphere_joint')
#検索
result = cmds.ls('pSphere*', geometry = True)
print(result)上記コードの実行結果は以下の通りです。
[u'pSphere_meshShape']最初に「pShere」と名前が共通するメッシュとジョイントのを作成しました。そこからlsの引数に「geometry = True」を渡すことでメッシュのシェイプノードのみを検索することができました。
処理を行う上ではシェイプノード名でも問題はありませんが、名前に「~Shape」が付かないトランスフォームノード名の方を取得したい場合もあります。
3D空間上に配置できるオブジェクト(ジョイント以外)は、必ずトランスフォームノードの子にシェイプノードという構成で作成されます。これは「Outliner」→「Display」→「Shapes」にチェックを入れることで確認することができます。
つまり、上の方法でシェイプノード名を取得し、その親を調べればアウトライナー上と同じ名前が取得できるわけです。
#-*- encoding: utf-8
import maya.cmds as cmds
#オブジェクトを作成
cmds.joint( p=(0, 0, 0) ,n = 'pSphere_joint')
cmds.polySphere(n = 'pSphere_mesh')
#検索
result = cmds.ls('pSphere*',geometry = True)
result = cmds.listRelatives(result,parent = True)#階層を調べる関数
print(result)上記コードの実行結果は以下の通りです。
[u'pSphere_mesh']関数listRelatives()はオブジェクトの親や子を調べることができます。第一引数にシェイプノードを渡し、第二引数にparent = Trueを渡すことで、親階層であるトランスフォームノードを返しました。
Mayaを触っていればわかると思いますが、ツールを実行する前にまずは処理を行う対象を選択しますね。Maya上で選択されているオブジェクトや頂点、エッジ、面の名前を取得するにはls関数を使用します。
#-*- encoding: utf-8
import maya.cmds as cmds
mesh = cmds.ls(sl = True) #slはselectionの略
print(mesh)試しにSphereオブジェクトを作成し、オブジェクトを選択した状態で上記のコマンドを実行すると以下のような結果が表示されます。
#オブジェクトを選択した場合
[u'pSphere1']
#オブジェクトのバーテックスを選択した場合(数字は各頂点のインデックス)
[u'pSphere.vtx[0]']
#オブジェクトのエッジを選択した場合(数字は各エッジのインデックス)
[u'pSphere.e[0]']
#オブジェクトのフェイスを選択した場合(数字は各フェイスのインデックス)
[u'pSphere.f[0]']選択したものの名前を取得する上でもう一つ重要なのが選択順です。
上記のコードのように引数selection(sl)を有効にした場合、オブジェクト単位では選択順にリストを返しますが、頂点やエッジ、フェイスは複数選択しても選択順で返してくれません。また、選択したコンポーネントのインデックスが連続した数字である場合、それらをまとめた一つの文字列で返します。
#pSphere.vtx[4],pSphere.vtx[2],pSphere.vtx[0]の順で選択した場合
[u'pSphere1.vtx[0]', u'pSphere1.vtx[2]', u'pSphere1.vtx[4]']
#pSphere.vtx[2],pSphere.vtx[1],pSphere.vtx[0]の順で選択した場合
[u'pSphere1.vtx[0:2]']ちなみに、pSphere1.vtx[0:2]のようにまとめた形にも利点があります。
Maya提供の関数は呼び出しに若干時間がかかり、処理の中で頻繁に呼び出すとかなり重くなります。コンポーネント一つ一つに処理を行う場合にはそのような状況が発生しますが、pSphere1.vtx[0:2]のようにまとまった形で引数に値を渡すことで関数を呼び出す回数が減るので、処理スピードを大幅に改善することができます。
コンポーネントの選択順リストを取得するためには関数lsの引数に「orderedSelection(os)」と関数selectPrefを用います。
#-*- encoding: utf-8
import maya.cmds as cmds
cmds.selectPref(tso = True) #tsoはtrackSelectionOrderの略
component = cmds.ls(os = True)
print(component)ls関数の引数「orderedSelection(os)」は有効にすることでコンポーネントを選択順でリストしますが、それはselectPref関数のtrackSelectionOrder(tso)の値に依存します。これが有効になっていない場合はls関数の引数「selection(sl)」を有効にした場合と同じ結果になります。
上記に示したコンポーネント選択例で再実行すると以下のような結果になります。
#pSphere.vtx[4],pSphere.vtx[2],pSphere.vtx[0]の順で選択した場合
[u'pSphere1.vtx[4]', u'pSphere1.vtx[2]', u'pSphere1.vtx[0]']
#pSphere.vtx[2],pSphere.vtx[1],pSphere.vtx[0]の順で選択した場合
[u'pSphere1.vtx[2]', u'pSphere1.vtx[1]', u'pSphere1.vtx[0]']ちなみに、「cmds.selectPref(tso = True)」で有効にした値は、「windows > Settings/Preferences > Preferences」を開き、「Categories > settings > Selection > Modifiers」の中にある「Track selection order」です。

前回までPythonの大まかな説明と学習方法などを説明してきました。
小難しいことが嫌いな人向けのMaya/Python入門①~Python編~
小難しいことが嫌いな人向けのMaya/Python入門②~準備編~
大まかな概念がわかったところで早速例題としてツールを作っていきます。
「え、いきなり!?」って思うかもしれませんが、Pythonについて知り尽くしてからってなるとモチベーションが続かないし、いざ使うときになって忘れてしまうので、分からないことがあったときにそれについて調べた方が記憶に定着すると思うからです。
というわけで今回作成するのは「ウェイト書き出し、読み込み」ツールです。
Mayaの標準ツールにウェイトマップで書きだす方法がありますが、UVをきれいに開かないといけないし、解像度によって精度と容量が左右されるのでデータとして使い勝手が悪い。
ポリゴンメッシュの頂点には必ず番号が割り振られているので、その頂点番号とウェイト値の組み合わせをテキスト形式でファイル出力すれば上記のような問題が解決できるはずです。
ツールのイメージとしては、ツールには「書き出し」ボタンと「読み込み」ボンタンがあり、ウェイトを書き出すメッシュを選択した状態で「書き出し」ボタンを押すとダイアログが開き保存先を指定しデータに書き出される。また、同じメッシュを選択した状態で「読み込み」ボタンを押すとダイアログが開き読み込みファイルを指定するとウェイトが読み込まれる。
という感じです。
上記の内容から必要そうな機能・処理をリストアップします。
これらの処理を一つ一つ作成していけばツールが出来ます。
#-*- encoding: utf-8
import maya.cmds as cmds
import json
def getSkinClusterName(mesh):
history = cmds.listHistory(mesh)
for i in history:
if cmds.objectType(i,isType='skinCluster'):
skinClusterName = i
return skinClusterName
def getWeight(mesh):
skinClusterName = getSkinClusterName(mesh)
numberOfVTX = cmds.polyEvaluate(mesh, v=True)
weights = {}
weights[mesh] = {}
for i in range(numberOfVTX):
weights[mesh][i] = {}
influenceList = cmds.skinPercent(skinClusterName,mesh+".vtx["+str(i)+"]", t = None, q = True)
for j in influenceList:
weight = cmds.skinPercent(skinClusterName,mesh+".vtx["+str(i)+"]", t = j, q = True)
if weight != 0:
weights[mesh][i][j] = weight
return weights
def putWeight(mesh,weights):
skinClusterName = getSkinClusterName(mesh)
numberOfVTX = cmds.polyEvaluate(mesh, v=True)
for i in range(numberOfVTX):
VTXWeight = []
for j in weights[mesh][str(i)]:
VTXWeight.append([j,weights[mesh][str(i)][j]])
cmds.skinPercent(skinClusterName, mesh+".vtx["+str(i)+"]", tv = VTXWeight)
def exportFile():
filePath = cmds.fileDialog2(fileFilter = '*.json', cap = '書き出し', okc = '書き出し',ds = 2, fm = 0)
if filePath == None:
return False
mesh = cmds.ls(sl=True)
WeightDate = {}
for i in mesh:
WeightDate.update(getWeight(i))
with open(filePath[0], mode = 'w') as fileWrite:
json.dump(WeightDate,fileWrite, indent = 2)
def importFile():
filePath = cmds.fileDialog2(fileFilter = '*.json', cap = '読み込み', okc = '読み込み',ds = 2, fm = 1)
if filePath == None:
return False
with open(filePath[0],mode = 'r') as fileRead:
weight = json.load(fileRead)
mesh = cmds.ls(sl=True)
for i in mesh:
putWeight(i,weight)
testWin = cmds.window(title='ウェイトの書き出し', width=280)
cmds.columnLayout(adjustableColumn=True)
cmds.button(label='書き出し',command='exportFile()')
cmds.button(label='読み込み',command='importFile()')
cmds.setParent('..')
cmds.showWindow(testWin)※↑コード中の隠れてしまっている部分は下のスライダーを移動すれば確認できます。
このコードは実際に作成したものです。一旦これをコピーしてスクリプトエディタで実行してみてください。
ツールの操作方法は以下の通りです。
【書き出し】
【読み込み】
動作確認ができたところで、それぞれの処理がどのように行われているか簡単に解説していきます。

まず、2~3行目に書かれているように一番上にはモジュールのインポートを記述します。使いたい機能によっては上記以外にもインポートする必要があります。
6~54行目で関数を記述し、その次に56~61行目でウィンドウ作成の記述をしています。この順番が実は大事。
スクリプトは基本的には上から順に処理が行われます。「def」ではじまる関数の記述は「作成」をしただけで、他の記述から「呼び出し」されるまで処理は行われません。その呼び出しを行っているのがウィンドウ作成処理の記述部分です。「書き出し」ボタンを押すとウェイトデータ書き出しに関する関数の呼び出し処理を行い、「読み込み」ボタンを押すと読み込みに関する関数を呼び出します。
重要なのは、上から順に処理が行われていった時に「関数の作成」前に「関数の呼び出し」を行っても「その関数はありません」と言われてしまうということです。
大まかにですが処理が進んでいく順番を解説します。どのように処理が進んでいくかを知ることで、コードを書くときの感覚がつかめるはずです。
「書き出し」ボタンを押したときの処理について大まかに説明しましたが、これだけでは詳細な処理内容についてはわからないと思います。Pythonの文法やMayaの関数については準備編で解説した通り調べることができます。そういったドキュメントを確認しながら上記のコードや解説を読むことでより理解が深まるはずです。
「読み込み」ボタンを押したときの処理内容は「書き出し」ボタンの処理と似ているので、応用として処理内容を追ってみると良いでしょう。
以下の「現場で使えるMayaスクリプティング」は実際に使えるコード集ですが、「maya.cmds」ライブラリをインポートして行うスクリプッティング(今回説明したような)ではなく、「PyMEL」のライブラリを使用したスクリプティングです。
本書ではPyMELの方がわかりやすく学習に向いているとのことで解説していますが、個人的にはその中でもMELと並行したPython基礎の解説(本書の3分の1ほど)がすごく参考になりました。
前回Pythonの大まかな説明をしました。
小難しいことが嫌いな人向けのMaya/Python入門①~Python編~
今回は準備編ということで、Mayaでのスクリプト記述方法や勉強方法などを紹介していきます。


Mayaの右下にエディターマークがあるので押すとスクリプトエディタが起動します。

ちなみに、下部ペインのタブは「+」タブを選択することで「MEL」または「Python」のタブを増やすことができます。書き途中のコードとは別に試験的なコードを作成し上手くいったら書き途中のコードに組み込んだり、参考のスクリプトを置いておいて一部コピペするなどに使えます。
また、公式のMaya HelpのPythonコマンドリストには必ず記述例が載っているので、コマンドの使い方を確かめるのによく使います。
スクリプトエディタのFile→Save scriptでpy形式で保存できます。
エディタに記述したスクリプトは、Mayaを落としても起動時に残っていることもありますが、複数立ち上げたMayaの落としたタイミングなどで保存されないこともあります。保存してなかったとして落とすときに確認のダイアログもでないので要注意です。
ここでもスクリプトについての記事を書いていこうと思いますが、一番大事なのは自習方法を知ることだと思います。
Pythonについては、ネットで調べればたくさんサイトがあり、基本的なことから詳細な事例までいろんなことが知れますし、mayaの機能を使うための関数なども公式のサイトにすべて載っています。
Pythonについて完璧に頭にインプットしてから書き始めるより、「こういうものを作りたい」というイメージを持ちながらそれに関するPythonの文法やMayaの関数を調べていった方が最短で効率的に学ぶことができると思います。
上で書いた通り基本的にはネットで調べれば情報は足ります。ただそもそもPythonってどんな感じで書くの?どんな概念があるの?ということがわからなければ調べようがありません。
一番効率的なのは1冊入門書を買ってみることです。本であれば一通りの概念が説明されているので、じっくりでもいいしパラパラ~でも目を通しておけば、「あ、こういうことも出来たんだ~」ってこともなくなります。
私のオススメは「みんなのPython」です。
MayaでPythonスクリプトを書いてみるといってもそもそも何ができるのわからなければ何から手を付けていいかもわかりません。そこで大切な考えが、
「手動で出来ることはスクリプトでも出来る」
と
「手動でやっていたことをスクリプトにやってもらう」
です。
Maya上のほとんどのツールはプログラム上で関数としてその機能を使うことができます。
今まで手動で行ってきた手順1~10をスクリプトにやらせたら楽なんだろうな~というところから始まり、「じゃあ、このツールの関数は?」と公式のドキュメントを探していけば、自ずと作り始めることができるはずです。
海外だけでなく日本サイトでも自作のスクリプトを無償でアップしている人がいます。
私の感覚ですが、完成された他人のスクリプトを観察するのが一番早いです。むしろ最初の一歩としてこれがないとかなり長い道のりになるといっても過言ではありません。
Mayaで目的の処理結果を出すにはどのようなデータが必要で、そのデータを取得するにはどの関数が必要で、データはどのような形式でどのように渡せばいいのかなど・・・
公式のドキュメントに関数は一通り載っていますが、数が多いのでどんな関数があるか一つ一つ調べていたら、いつまでたってもスクリプトは完成しません。
私の場合、勉強のために初めて作ろうとしていたスクリプトと似た処理をするスクリプトをたまたま見つけ、半月くらいで完成させることができました。また、その中には今後にも応用できる処理があったので、2個目3個目と作成するのにさほど時間がかかりませんでした。

まずgoogleで検索し「Maya ヘルプ – Autodesk Help」を開き、[テクニカルドキュメント]→[Pythonコマンド]を開きます。

並んでいる英字がMayaの関数です。

関数のリンクを選択するとその関数の概要や戻り値、フラグ(引数のこと)の種類と説明などが掲載されています。
ページの一番下にはその関数を使用したプログラム例が載っているので、ぱっと見何をする関数かわからないときはコピペで実行してみるといいかもしれません。
とりあえず、本題に入る前に基本的な操作方法やついでに勉強方法を説明させて頂きました。次回は実際にプログラムを書きながら説明をしていきます。
スクリプト?何それ怖い・・・っていう文系デザイナーのために、とりあえず実用的なツールを作りながら、MayaでのPythonスクリプト書き方を極力簡単に説明していきます!
プログラミング言語です。(え、それくらい知ってるって?)
プログラミングで行うことをざっくり説明すると、数値や文字列を変数という入れ物に入れ、それをそれぞれ「〇〇〇文」という処理方法を指示する文で計算を行い結果を出力します。・・・いや、本当にこれだけのことです。
つまり、「変数」と「〇〇〇文」、プラス「関数」を覚えればプログラム(スクリプト)は書けます(え?一つ増えたって?)。
学生のころみんなが大好きだった数学で「x = 1」とか「y = 2」とかってやりましたね。この「x」や「y」がプログラミングでいう変数です。
数学で「x = 1」は「xは1ですよ!」って意味だったのに対し、プログラミングでは「xという入れ物に1という数字を入れますよ!(代入)」という意味であり、値が入った変数を各処理間でやり取りを行います。
#「英数字 = 値」の形で記述するだけで変数の作成と値の代入ができる
x = 1
#大体何の値を扱っているかわかる変数名をつける(任意)
finger = 5
#数字から始まる変数は作れない
2manEar = 4
#プログラムの文法上他の意味を持っている文字列は変数としては使えない
not = 0数学で扱うのは数字だけですが、プログラミングでは文字列やリスト、タプル、整数、浮動小数点など扱うデータに種類があり、それぞれに「型」があります。
「型」は代入した値によって勝手に決まるものなので、値を入れる分にはあまり型を気にすることはありませんが、後に変数を処理で扱う際には変数の「型」が何であるかが重要になってきます。
#整数型(int型とも言う)
ABC = 1
#浮動小数点数型(float型)
ABC = 0.5
#文字列型(string型)
ABC = 'abc'
#リスト型(list型)
ABC = ['abc', 123, 0.1]
#辞書型
ABC = {name:'Tarou', age:30}
#bool型
ABC = True
ABC = False最初に説明した「〇〇〇文」の一つ。
num = 5
if num >= 4:
print('正解!!')
else:
print('不正解・・・')
#実行結果は、「正解!!」と表示されます。上記「if」の横に書かれている「num >= 4」は「numという変数に入っている数値は4以上だ」ということを意味しており、もしこれが正しければ3行目にインデント(空白部分)を開けて書かれた「print(‘正解!!’)」が実行されます。
仮に1行目が「num = 3」だった場合、4行目の「else:」の後に書かれている「print(‘不正解・・・’)」が実行されます。
このように、「if 〇〇〇:」の〇〇〇部分に条件を書くことでそのあとの処理を実行させるかどうかをプログラムに判断させるわけです。
ある処理を決められた回数繰り返させるのが「for文」です。
for num in range(10):
print(num)実行結果から言うと、「0123456789」と表示されます。
ここで行われた処理を説明すると、range(10)から0という数値が出力→それがforの後ろにあるnum変数へ代入→2行目のprint(num)でnumの中身を表示→range(10)から1→numへ代入→numの中身を表示→・・・・
という感じで同じ処理を10回繰り返します。
このようにinの後ろにあるものから1つずつ要素を取り出し、処理にそれを利用しつつ、その要素の数だけ処理を繰り返すのがfor文です。
ちなみに、「range(〇〇〇)」は〇〇〇に入れた数字を0から順番にその数字の個数返していく処理をします。つまり、10と入れると「0 1 2 3 ・・・9」と返します。
Mayaのスクリプトでは初めに以下のように記述します。
import maya.cmds as cmdsimport文はこのあとにも説明する「関数」などの機能が詰め込まれたモジュールを読み込むための記述です。
上の記述はMaya内の様々な機能を使うためのモジュールを読み込んでいます。とりあえず必ず書くってことを覚えておけば大丈夫です。
数学で1次関数とか2次関数とかってやりましたね・・・。
「y = 2x+8」についてx=-5のときyの値を求めよ!みたいな。
プログラミングでいう関数もある意味同じで、「引数(x)が〇〇のとき戻り値(y)は●●です!」という感じで処理をしてくれます。
つまり、何かしら値を渡すと決まった処理を返してくれるのが関数です。
関数は「自分で作って使う」場合と「Pythonまたはソフト側で提供しているものを使う」場合があります。
import math
def getDistance(A,B):
dis = math.sqrt((B[0] - A[0])**2 + (B[1] - A[1])**2 + (B[2] - A[2])**2)
return abs(dis)
positionA = [5,6,7]
positionB = [8,9,10]
distance = getDistance(positionA,positionB)
print(distance)プログラム内では同じ処理を何回も使うことがあります。それらを毎回書いているとコードが長くなって分かりづらいうえ、処理を修正する際にも一つ一つ書き換える必要が出てきます。
関数化によって処理をまとめてしまえばそれらを解決することができます。
例えば上記のコードは2つの座標から距離を計算する処理を関数化しています。処理自体は1行ですが何回も使うので関数化した方が便利です。
2~4行目で関数の定義を行っており、「def」の後に関数名つづいて()内に入力に当たる変数A,変数Bを記述しています。そして3行目は実際の処理である計算式を記述し、4行目の「return」のあとに返す値(変数)を記述することで関数の出来上がりです。
6,7行目ではX、Y、Zの座標を示す変数を定義しています。
そして8行目で作成した関数に変数を渡し、帰ってきた距離の値を「distance」変数に代入しています。
9行目の「print(distance)」で距離を表示させています。
import maya.cmds as cmds
cmds.polySphere(sx=10, sy=15, r=20)上記のコードは名前の通りpolySphereを作成する関数です。
1行目でインポートしているモジュールはMayaの機能を使うための関数が用意されています。
そして、3行目がpolySphereを作成する関数です。引数の「sx=10」はX方向のサブディビジョン、「sy=15」はY方向のサブディビジョン、「r=20」は半径の幅を指定しています。
引数の渡し方についても、『複数回使う処理は関数化する』で出した例(8行目)のように、渡す変数のみ記述するのが一般的ですが、上記例のように「それぞれの関数に用意された引数名」=「値」という書き方もあります。
mayaの関数の書き方は後者で、関数名とその関数が持っている引数名については以下の方法で調べることができます。
「maya help」で検索→「Mayaヘルプ – Autodesk Help」を開く→「テクニカル ドキュメント」→「Pythonコマンド」
とりあえず、Pythonについてざっくりと知って頂ければ大丈夫です。細かいことは分からなくても、どんな概念があるのかということだけ知っていればいくらでも調べることができるので。大事な流れは抽象から詳細。
スキンウェイトペイントツールに関するトラブルをまとめます!
ウェイトペイントツールで塗ったはずが再選択した瞬間に戻っている、消したはずが戻っているという現象が起きることがあります。
これはインフルエンスの移動先・移動元をロックしていることにより、ウェイトが移動しようがない状態にしてしまっていることが原因です。
一つの頂点には複数のインフルエンス(影響しているジョイント)がウェイト値を持つことがありますが、必ずその合計値は1.0になるという決まりがあります。
合計値が必ず1.0になるということは、ある頂点に付いているAというインフルエンスのウェイト値のみを編集するにしても、Aにプラスした分は他のインフルエンスからマイナスしなければならないし、Aからマイナスした分も他のインフルエンスにプラスする必要があります。
例えばそのある頂点がA以外にBとCのウェイト値を持っていた場合、BとCをロックしていたとするとAはウェイト値を上げることができません。
または、Aのウェイト値を下げるにしてもBとC、もしくはウェイト値を持たない他のインフルエンスを含めた全てをロックしているとできません。
ウェイト値を移動できない状態で編集しても、ペイントによる色の変化は反映されるので編集できているように見えるのですが、編集インフルエンスを切り替えたときに元のペイント状態にリフレッシュされるので、編集が戻ってしまったように見える訳です。
付けたはずのウェイト値が消えていたり、逆に付けたはずのないインフルエンスのウェイト値が付いていたりすることがあります。
原因は以下の3つです。
■ウェイト値を持つインフルエンスをロックして調整している
■ウェイト値を1.0持つインフルエンスを編集してしまった
■最大インフルエンス数の保持を設定している
上二つは以下の記事でもまとめましたが、これにより付けたはずのないインフルエンスのウェイト値が付いているという現象が起きます。
調整を楽にするスキンウェイトペイントの使い方【Mayaリギング】
最大インフルエンス数の保持は一つの頂点に付くインフルエンスの数をリアルタイムで制限する設定です。
例えば、最大インフルエンス数を3に設定し保持の設定をオンにすると、ある頂点に対して4つ目のインフルエンスのウェイト値を追加すると元から付いていたインフルエンス3つの内どれかがごっそり0になり、追加したインフルエンスに全て移ります。つまり、最大インフルエンス数が3つに保持された訳です。
この設定の挙動を知らないで設定していると、調整したはずのウェイトが急に消えたもしくは編集したときよりウェイト値が強くなるバグのように感じるのです。
キャラクターを動かす上でどうしても必要となる面倒な作業「ウェイト調整」。そのウェイトの調整によく使われるスキンウェイトペイントツールですが、意外と知られていない機能があるんです(たぶん)。
公式のヘルプを見ればわかることですが、実際の作業で重要な機能や考え方を中心に紹介していきます。
まず、ウェイトの正規化の欄をチェックしてください。「インタラクティブ」以外になっていたら直しましょう。これはある頂点に登録されているインフルエンス(ジョイント)のウェイト値の合計が必ず1になるようにリアルタイムで調整されるモードです。ポストとオフを使うことはほぼないです。

バインドするときは「最大インフルエンス数の保持」をオフにしましょう。もしすでにバインドしてしまっている場合はメッシュのアトリビュートからskinClusterタブを選択し、その中に同じく項目があるのでオフにします。
これは一つの頂点に登録できるインフルエンス数をリアルタイムで制限するもので、予想外にウェイトが消えたり知らないウェイトが付いたりするので混乱の元です。

ウェイトをペイントしたときにウェイト値がどのように推移するか説明された文章というのは意外とありません。そして、それがウェイト調整を混乱させ苦手としてしまう要因だと思います。
インフルエンスリストの中から編集したいインフルエンスを選択することで、そのインフルエンス(ジョイント)のウェイト値を編集することができます。その時ウェイト値を「どこから持ってくるかどこに逃がすか」ということを考える必要があります。一つの頂点のウェイト値は必ず合計が1.0になるという設定なので、あるインフルエンスのウェイト値を上げたら他のインフルエンスのウェイト値はその分差し引かれるし、またあるインフルエンスのウェイト値を下げたら他のインフルエンスのウェイト値がその分増加します。

例えば、
jointAからjointDまであるスケルトンをメッシュにバインドしたとき、ある頂点にjointA、jointB、jointCのウェイトが付いたとする。
jointAのウェイト値を上げたり下げたりした場合ウェイト値はjointBとjointCの中で推移し、元々ウェイト値が付いてなかったjointDにはウェイト値は流れない。

上記の例で言うなら、各インフルエンスのウェイト値がjointAが0.2、jointBが0.2、jointCが0.6の場合(計1.0)、jointAのウェイト値を0にするとjointBは0.25(0.05増)、jointCは0.75(0.15増)になります。
jointA以外のインフルエンスが持っているウェイト値合計0.8を100%とし、各インフルエンスが保有しているウェイト値はBが25%でCが75%なので、jointAのウェイト値0.2の25%=0.05はjointBへ、75%=0.15はjointCへ流れます。
リストのインフルエンスの横にはロックボタンそれぞれ付いています。ウェイト調整に伴うウェイト値の推移をロックしたインフルエンスにおいて制限することができます。
基本的な挙動は以下の2つです。
■ロックしたインフルエンス(ジョイント)のウェイトは、他インフルエンスからの影響を受けない。
■編集状態(リストで選択した状態)のインフルエンスはロックをオンにしても編集できる。つまり、編集はできるが他からの影響は受けない。
これに伴うウェイト値の推移例は以下の通りです。
■jointAのウェイト値を0.0と入力したとき、jointBがロックされているならウェイト値はすべてjointCへ
■jointAのウェイト値を0.0と入力したとき、jointB、jointCがロックされているならウェイト値はjointDへ
■jointAのウェイト値を0.0と入力したとき、jointB、jointC、jointDがロックされているならウェイト値は変化せず現状維持。
■jointAのウェイト値を1.0と入力したとき、jointBがロックされているならjointCが保有しているウェイト値のみ移動。
■jointAのウェイト値を1.0と入力したとき、jointB、jointCがロックされているならウェイト値は変化せず現状維持。
■jointAのウェイト値を1.0と入力したとき、jointB、jointC、jointDがロックされているならウェイト値は変化せず現状維持。
ちなみに、ロックするときは「選択範囲の反転」を有効活用しましょう。

ある頂点のあるインフルエンスのウェイト値が減少したとき、ウェイト値を保有し推移できるインフルエンスが他にない場合、頂点の近くにある適当なジョイントにウェイト値が飛びます。
具体的に言うと以下の場合です。
■ウェイト値が1.0のインフルエンスを編集
■ウェイト値が付いたインフルエンスを全てロック、それ以外にロックされてないインフルエンスがある。
大抵の場合頂点には複数のインフルエンスが付いており、あるインフルエンスを増減させてもいい感じにウェイト値を振り分けてくれるため何も考えずに編集してしまうが、同じ感覚で1.0のウェイト値がついた頂点をウッカリ触ってしまいいつの間にか変なウェイトが入っているというのが前者の場合です。

後者によくあるのは、基本的にウェイト値が付いたインフルエンス内で値が推移するので、ウェイト値が付いたインフルエンスだけ気にしてロックを入れてると、いつの間にかウェイトの流れる先を全て塞いでしまい氾濫してしまう場合です。

このミスによっていつの間にか変なウェイトが入ってしまい、何か特定の動きをしたときにはじめてミスに気が付くというのはよくある話です。特にジョイントが多かったりメッシュが細かかったりした場合は原因を探すのは大変です。
このトラブルを防ぐには、
「調整に関係ないインフルエンスを全てロックする」ということを心掛けることです。
これにより少なくとも全く予想外なインフルエンスが入ってくるということは防ぐことができます。
調整に関係あるインフルエンスとは、以下の2つです。
■ウェイトペイントで調整するインフルエンス
■ウェイトが移る先orウェイトを引っ張ってくる先のインフルエンス
つまり、
この流れを癖にして必ず守れば最悪な事態は回避できるはずです。
インフルエンス(ジョイント)が多いキャラクターなどの場合、インフルエンスの数が数十個、数百個とかになることがあります。そうなるとペイントツールのインフルエンス一覧の中から目的のインフルエンスを毎回探すのは骨の折れる作業です(スケルトンだけに)。
スムーススキンバインドなどである程度近くのジョイント(インフルエンス)のウェイトがメッシュについているなら、調整したい頂点のインフルエンスをこの方法で効率的にインフルエンスを探すことができます。
手順は以下の通りです。

ピンはペイントツールを閉じても保持されるので、作業中はインフルエンスを探す手間が省けます。
ちなみに頂点選択状態を解除する場合「ジオメトリの選択」ボタンを押すと頂点選択からジオメトリ選択に切り替わるので、いちいちツールを閉じる手間が省けます。

ウェイトの表示の仕方です。デフォルトでは白黒のグラデーションですが、ウェイト値がどれくらい入っているか視認しにくいと思います。カラーランプを使用すると彩度のある細かいグラデーションでウェイト値を表現するので調整し易くなります。

調整をしていると間違えて変なところにウェイト値を振ってしまったり、もしくは一部消してしまったりすることがあると思います。そんなときとりあえず良い感じでウェイト値を調整してくれるのがハンマーツールです。
選択した頂点に適用するとその周辺のウェイト値を拾って馴染ませてくれます。
ただインフルエンス数制限のあるプロジェクトでは余計にインフルエンスが増えてしまったり、もしくは広い範囲で適用したときに予想外に馴染ませすぎる場合もあるのでご注意ください。

blendColorsノードを用いて、IK/FKを切り替え・ブレンドできるスイッチを作成します。
↓↓持ち手用ジョイントにコントローラーを付ける方法につきましては、以下の記事をどうぞ
コントローラー設定基礎!一番単純な作り方【Mayaリギング】
↓↓通常のIK-Handle設定方法につきましては、以下の記事をどうぞ
IKハンドルの設定基礎!一番単純な作り方【Mayaリギング】
地面に接地して歩く脚のリグであれば大抵はIKハンドルで動かすのがベストですが、ジャンプをしたり、宙に浮いたりしたときは、FKで動かした方がベストな場合が出てきます。
今回作成した簡単なIK/FKスイッチだけで、切り替えだけでなくブレンドもできます。キャラクターのリグなら必須なので参考にして頂ければ幸いです。
スプラインIKに伸縮性を追加します。
↓↓単純なSplineIK設定方法は、以下の記事をどうぞ
スプラインIKコントローラーの一番単純な設定方法【Mayaリギング】
↓↓持ち手用ジョイントにコントローラーを付ける方法につきましては、以下の記事をどうぞ
コントローラー設定基礎!一番単純な作り方【Mayaリギング】
↓↓通常のIK-Handle設定方法につきましては、以下の記事をどうぞ
IKハンドルの設定基礎!一番単純な作り方【Mayaリギング】
まず、伸び縮みさせるための計算は割と単純ですが、
伸縮したカーブの長さ(curveInfoからの値)/元のカーブの長さ(非変形時の数値)=伸縮の倍率(X軸のスケールへ)
そこから、応用で窄まりと膨張の設定時に使った計算式ですが、
単純に伸びたら窄まり、縮んだら膨張すればいいので
計算式:1/x

1/xグラフ
これでもいいのですが、例えば2倍の長さになったときに細さが1/2になるので、ゴムのような表現にしてはだいぶ急な窄まりです。
そこで、以下の計算式ですが、
計算式:1/√x

1/(x^0.5)グラフ
累乗の計算が入るとなんだか難しそうな計算に見えるのですが、グラフを比較してもらえればわかるように、値の変化が緩やかになりました。
これぐらいの変化率の方がゴムのような表現には適しているわけです。
日本のアニメやゲームではあまり伸び縮みはないと思いますが、公式や海外の人が作ったリグを見ると大体伸び縮みできるように設定してあるように感じます。(そんなことない?w)
伸縮性設定の方法については、知ってしまえば意外と簡単なので、覚えてしまいましょう!
スケルトンにスプラインIKを設定すること自体は数クリックでできますが、そこに「ねじり対応設定」+「持ち手作成」までして初めてリグとして利用できるので、その一連の流れを説明します。
↓↓持ち手用ジョイントにコントローラーを付ける方法につきましては、以下の記事をどうぞ
コントローラー設定基礎!一番単純な作り方【Mayaリギング】
↓↓通常のIK-Handle設定方法につきましては、以下の記事をどうぞ
IKハンドルの設定基礎!一番単純な作り方【Mayaリギング】
人間や動物の背骨のように関節が多く滑らかに曲がるようなものには良く使われ、カートゥーンアニメーションなんかの場合にも腕や脚にも関節を増やし、スプラインIKが用いられることがあるようです。今回説明した内容はスプラインIKを用いるのに最低限必要な設定なので、セットで覚えておくといいかもしれません。