MAYA RUN作成の便利ツールを作りたい
キャラクターを走らせる際、片足からアニメーションを作って、それをもう片方にアニメーションをコピーさせて半分フレームをずらすというやり方で作成しているのですが、これを1ボタンでコピーとずらしをやって欲しいなと思うことが度々あります。
これができれば片側だけでアニメーションが作れてしまうので作業時間が短くなるし、あると便利だろうな。
ということで早速作ってみたいと思います。
作り方はPythonで作ってみようと思います。
いったん手順を言語化するとこんな感じ。↓
原点にロケーターを作成
原点にnullを作成
nullにロケーターを入れる
右足の各所にnullをポイントコンストする
nullの中のロケーターをアニメーションベイクする
nullのコントレインを削除
左足にnullをポイントコンストレイントする
左足をロケーターにペアレントコンストする
左足をアニメーションベイクする
ロケーターとコンストレイントを削除する
ベイクしたアニメーションを総フレームの半分ずらす
これをpythonで書いてみる。
import Maya comes as cmds
locater = cud’s.ls(selection = True)
#原点にロケーター作成
for locater in locaters:
locater = cmds.spaceLocator( p=(0,0,0))
cmds.rename(locater,’dmy_loc1’.format(locater))
#原点に空グループ作成
for locater in locaters:
locater = cmds.CreateEmptyGroup( p=(0,0,0))
cmds.rename(locater,’dmy_nul1’.format(locater))
#nullにロケーターをペアレントする
cmds.parent("dmy_loc1","dmy_nul1", relative=True )
cmds.parent("dmy_loc2","dmy_nul2", relative=True )
cmds.parent("dmy_loc3","dmy_nul3", relative=True )
cmds.parent("dmy_loc4","dmy_nul4", relative=True )
#nullを左足の各箇所にポイントコンストレイン
cmds.pointConstraint( "L_joint1","dmy_nul1" )
cmds.pointConstraint( "L_joint2","dmy_nul2" )
cmds.pointConstraint( "L_joint3","dmy_nul3" )
cmds.pointConstraint( "L_joint4","dmy_nul4" )
#ロケーターを左足の各箇所にペアレントコンストレイン
cmds.parentConstraint( "L_joint1","dmy_loc1" )
cmds.parentConstraint( "L_joint2","dmy_loc2" )
cmds.parentConstraint( "L_joint3","dmy_loc3" )
cmds.parentConstraint( "L_joint4","dmy_loc4" )
#アニメーションをベイク
locaters = ["dmy_loc1","dmy_loc2","dmy_loc3","dmy_loc4",]
for locater in locaters:
st = int(cmds.playbackOptions(min =1, q =1))
ed = int(cmds.playbackOptions(max =1, q =1))
cmds.bakeResults( locater, t =(st,ed), at = ["tx","ty","tz","rx","ry","rz"])
#コンストレイン削除
cmds.delete(
"dmy_nul1_pointConstraint1","dmy_nul2_pointConstraint1","dmy_nul3_pointConstraint1","dmy_nul4_pointConstraint1",)
#アニメーションカーブをサイクルに変更
locaters = ["dmy_loc1","dmy_loc2","dmy_loc3","dmy_loc4",]
for locater in locaters:
cmds.setInfinity( locater, poi = 'cycle', pri = 'cycle')
#逆側にコンストレイン
cmds.pointConstraint( "R_joint1","dmy_nul1" )
cmds.pointConstraint( "R_joint2","dmy_nul2" )
cmds.pointConstraint( "R_joint3","dmy_nul3" )
cmds.pointConstraint( "R_joint4","dmy_nul4" )
#コンストレイン削除
cmds.delete(
"dmy_nul1_pointConstraint1","dmy_nul2_pointConstraint1","dmy_nul3_pointConstraint1","dmy_nul4_pointConstraint1",)
#各箇所コンストレイン
cmds.parentConstraint( "dmy_loc1","R_joint1" )
cmds.parentConstraint( "dmy_loc2","R_joint2" )
cmds.parentConstraint( "dmy_loc3","R_joint3" )
cmds.parentConstraint( "dmy_loc4","R_joint4" )
#アニメーションをベイク
locaters = ["R_joint1","R_joint1","R_joint3","R_joint4",]
for locater in locaters:
st = int(cmds.playbackOptions(min =1, q =1))
ed = int(cmds.playbackOptions(max =1, q =1))
cmds.bakeResults( locater, t =(st,ed), at = ["tx","ty","tz","rx","ry","rz"])
うまく行くと思ったんですが、右足にアニメーションを移す際にコンストレイントの重複が起きたりエラーになったりしてうまくいかず、、、
違う方法を考えてみることに。
ここでconnectAttrというコマンドを見つけました。
コンストレイントをつけなくても2つ指定すれば動きが同じになる方法です。
移動値を同じにすると両足がくっついてしまうので回転値だけ同期させる方法でやってみます。
connectAtrrで両足の回転値を同期させる
同期した片足をベイクする
同期を解除する
アニメーションカーブをサイクルに変更
アニメーションを全選択し総フレームの半分ずらす
import Maya.cmds as cmds
#connectAtrrで両足の回転値を同期させる
cmds.connectAttr(‘L_joint1.r’,’R_joint1.r’)
#同期した片足をベイクする
joints = [“R_joint1”]
start = int(cmds.playbackOption(minTime=1,query=1)
end = int(cmds.playbackOption(maxTime=1,query=1)
cmds.bakeResults(joints,t=(start,end),at=[“tx”,“ty”,“tz”,“rx”,“ry”,“rz”],simulation=True)
#同期を解除する
cmds.disconnectAttr(‘L_joint1.r’,’R_joint1.r’)
#アニメーションカーブをサイクルに変更
joints = [“R_joint1”]
for n in joints:
cmds.setInfinity(joints,poi = ‘cycle’,pri = ‘cycle’)
#アニメーションを全選択し総フレームの半分ずらす(手入力)
import maya.cmds as cmds
def Time_Offset():
Offset_Number = cmds.textField( "Time_Offset", q=True, tx=True )
selected_object = cmds.ls( type=['animCurveTL','animCurveTU','animCurveTA','animCurveTT'])
cmds.keyframe(selected_object,edit=True,relative=True,timeChange=Offset_Number)
cmds.window(title="offset")
cmds.columnLayout()
cmds.textField( "Time_Offset" )
cmds.button( l="総フレームの半分の値を入力する", command="Time_Offset()" )
cmds.setParent( '..' )
cmds.showWindow()
これでいったんやりたいことができたかな。
まだ汎用性が低いのと、タイムスライダーを手入力で入れるのはダサいけど…。
次はどのモデルでも対応できるものを作ろう。