MAYA RUN作成の便利ツールを作りたい

キャラクターを走らせる際、片足からアニメーションを作って、それをもう片方にアニメーションをコピーさせて半分フレームをずらすというやり方で作成しているのですが、これを1ボタンでコピーとずらしをやって欲しいなと思うことが度々あります。

これができれば片側だけでアニメーションが作れてしまうので作業時間が短くなるし、あると便利だろうな。

ということで早速作ってみたいと思います。

作り方はPythonで作ってみようと思います。
いったん手順を言語化するとこんな感じ。↓

  1. 原点にロケーターを作成

  2. 原点にnullを作成

  3. nullにロケーターを入れる

  4. 右足の各所にnullをポイントコンストする

  5. nullの中のロケーターをアニメーションベイクする

  6. nullのコントレインを削除

  7. 左足にnullをポイントコンストレイントする

  8. 左足をロケーターにペアレントコンストする

  9. 左足をアニメーションベイクする

  10. ロケーターとコンストレイントを削除する

  11. ベイクしたアニメーションを総フレームの半分ずらす

これを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つ指定すれば動きが同じになる方法です。
移動値を同じにすると両足がくっついてしまうので回転値だけ同期させる方法でやってみます。

  1. connectAtrrで両足の回転値を同期させる

  2. 同期した片足をベイクする

  3. 同期を解除する

  4. アニメーションカーブをサイクルに変更

  5. アニメーションを全選択し総フレームの半分ずらす


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()


これでいったんやりたいことができたかな。
まだ汎用性が低いのと、タイムスライダーを手入力で入れるのはダサいけど…。
次はどのモデルでも対応できるものを作ろう。





いいなと思ったら応援しよう!