HEXA BLOG

その他

HEXA BLOGその他2017.5.26

TAとUE4 SKeletalMesh Animation

こんにちは、Ritaro です。

 

 こちらに記事を書くのはこれで3回目となります。

今回も、どうぞよろしくお願い致します。

 

  TAにとって開発上の問題点を解くのに 技術的な引き出しを色々な持っておくことが必要、

と以前の記事に書いた部分を・・また少し紹介したいと思います。

 

幾つかのゲームを開発していると、 作品を開発する上で必要なツール回りやミドルウェアで対応しておくべきデータ類、確立しておくべきワークフローなど幾つか予想できる パターン がみえて来たりします。

新しいツールを使い始めた時など、特にこれがみられます。

 

実は、一番初めのBlogに書いた “カメラ” などはその典型的なデータです。

必ず使うデータであり、重要なデータです。

また、うまく連携出来なかった場合の対応までを考えておき、正しいデータが 実装できる確実なワークフローをみつけておくことも重要です。 手順によっては結果が異なる場合は特に気を付けるべきであり、 何が原因でそうなるのか時間をかけてでも究明しておけば、 そのノウハウは必ず後で役に立ちます。

実は昨日も 『 カメラの実装が~ 』 と フイ に問い合わせがあり  

その場で ”解決出来た~” がありました。

 

  カメラ に引き続き、今度は アニメーション についても重要です、 が今回の話です。

 

ちょっと具体的な、面白い対処法、でもあったら『おお、使えるかも』

・・って思うようなものをまた1つご紹介してみましょう。

 


 

「MayaのポリゴンのアニメーションをUE4で簡単に動かしたい!!」

 

  Mayaを使ってポリゴンにアニメーションを設定して、それをUE4で動かしたい、とします

例えば10個とか50個とか、独立した個々のポリゴンが爆発エフェクトのように

バ~ン!! と動いていて、それをUE4でアニメーションとして実装したい、などです。

すると、気付くのは、UE4は SkeletalMesh でないとアニメーションとして動いてくれない という点です。

数個ならBluePrintやLevelSequencer上にキーを打つ事も出来るとは 思いますが、

すでにMaya上で動いている50個ものポリゴンとなると・・

 

  そこで、Maya上でちょっとしたツールを用意して作業の高速化を図る訳です。

 

こんなアプローチでどうぞ。

 

『 ポリゴン群は1つのGroupの子供達とします。

  各ポリゴンの最初の位置に1つJointを作成して、

  位置コンストレイントを付けておいて

  ベイク・シミュレーションを実行してアニメーションをJointに移し、

  ポリゴンはそのJointにSkinBindする  』

をスクリプト化します。

 

まずはポリゴン1個の場合で動かしてみましょう。

Cubeにアニメーションが付いていて、親がGroupになっています。

 

*— ”前々準備” ——————

 pCube1 ポリゴン

 ● 回転ピボットの位置指定 ポリゴンモードで 移動と回転時はこちらが選択される

             ローカル回転ピボット cmds.xform(‘pCube1’, rotatePivot=(0.0, 0.0, 0.0))

             ワールド回転ピボット cmds.xform(‘pCube1’, worldSpace=True,rotatePivot=(0.0, 0.0, 0.0))

 ● スケールピボットの位置指定 ポリゴンモードで スケール時、Insetキーで編集時はこちらが選択される

            ローカルスケールピボット cmds.xform(‘pCube1’, scalePivot=(0.0, 0.0, 0.0))

            ワールドスケールピボット cmds.xform(‘pCube1’, worldSpace=True,scalePivot=(0.0, 0.0, 0.0))

*———————

 

(GUI部分は記載しておりません)

<ツールは自己責任でお使いください>

 

import maya.cmds as cmds


d_sel = cmds.ls( selection=True )[0]

# Get Parent 

a_parent = cmds.listRelatives(d_sel, parent=True,type='transform', path=True)[0]


al = cmds.xform(a_parent,pivots=True,q=True)

aw = cmds.xform(a_parent,worldSpace=True,pivots=True,q=True)

cx = al[0] - aw[0]
cy = al[1] - aw[1]
cz = al[2] - aw[2]

dw = cmds.xform(d_sel,worldSpace=True,pivots=True,q=True)

ex = dw[0] +  cx
ey = dw[1] +  cy
ez = dw[2] +  cz

cmds.select(clear=True)
#print ex,ey,ez
new_joint = cmds.joint( p=(0, 0, 0) )
cmds.parent( new_joint, a_parent )
cmds.setAttr(new_joint + '.translate', ex, ey, ez)

cmds.setAttr(d_sel + '.translateX',lock=False)
cmds.setAttr(d_sel + '.translateY',lock=False)
cmds.setAttr(d_sel + '.translateZ',lock=False)
cmds.setAttr(d_sel + '.rotateX',lock=False)
cmds.setAttr(d_sel + '.rotateY',lock=False)
cmds.setAttr(d_sel + '.rotateZ',lock=False)

cmds.select(clear=True)
cmds.select(d_sel)
cmds.select(new_joint)
cmds.parentConstraint( d_sel, new_joint,weight=1.0 )

cmds.select(clear=True)
cmds.select(new_joint)

min = cmds.playbackOptions(query=True,minTime=True)
max = cmds.playbackOptions(query=True,maxTime=True)

cmds.bakeResults( new_joint,attribute='rotate',time=(min,max),simulation=True )
cmds.bakeResults( new_joint,attribute='translate',time=(min,max),simulation=True )
cmds.delete(new_joint + '_parentConstraint1')

cmds.cutKey(d_sel)

cmds.skinCluster( new_joint,d_sel,toSelectedBones=True,bindMethod=0,normalizeWeights=1,maximumInfluences=1, dropoffRate=4.0)

 

 で一回分ですが、これをポリゴン数の分、ベイク処理したら たまったもんじゃ~ ありません。
そこで、ここは作ったJoint分のリストを作成しておいて、1回だけのベイクにします。

 

joint_list = []
joint_names = ','.join(joint_list)
min = str(cmds.playbackOptions(query=True,minTime=True))
max = str(cmds.playbackOptions(query=True,maxTime=True))
exec 'cmds.bakeResults(' + joint_names + ',time=(' + min + ',' + max + '),simulation=True )'

 

joint_list が [u’joint1′, u’joint2′] だった場合、

joint_names は joint1,joint2 となり、そのJointの数分を一気にベイクします。

UE4のMatineeに置いた場合の例が下図です。

 

    20170526_cha

 

今だとLevelSequencerの方を使うと思いますが、同様に使えます。

 

ではでは。

*—–

Ritaro

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE