CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

Babylon.js Editor v4.2.0でキャラクタが炎の魔法剣を振るモーションを作る方法

以前からBabylon.jsでキャラクタを動かす方法を色々と調べています。特に理由はないのですがキャラクタを動かす方法を調べていく中で、ダイの大冒険6巻で登場した「火炎大地斬」を再現してみようと思って、炎の魔法剣を作って剣を振るモーションを作ってみました。

今回は剣を振るモーションを作る方法について解説します。

1 剣や銃を腕と一緒に動かすには、BabylonjsのattachToBoneを使う

今回やりたかったのは腕の振りに合わせて剣を動かすことです。調べてみるとforumで全く同じ質問をしている人がいました。
(ここではBlenderのconstraintをBabylon.jsで使えないかという趣旨の質問ですが、やりたいことは一緒と判断しました。constraintについてはこの記事の後ろの方に書きました)

www.html5gamedevs.com

フォーラムの中では質問と回答が続きますが、今回は途中のこの文章で紹介されているリンク (Babylon.js公式ドキュメント)が役立ちました。

There are multiple ways, I think. The way to do it on the JS side is.

ここのリンクで紹介されているattachToBoneで解決します。これは指定したオブジェクトをboneにくっつける処理です。どんなものかは以下のPlaygroundがわかりやすいです。

Moving dude in Babylon.js Playground

Moving dude in Babylon.js Playground

ここでは左手にsphereをくっつけており、歩くときの腕の振りにsphereが同期しています。今回やりたいことを実現するには、このsphereを自分で用意したswordに変更すればよいことになります。

そのためのコードはこれです。

gist.github.com

getBoneByNameについてですが、playgroundではskeleton変数を使っているのですが、Editorで試すときは取得ができなかったので使っています。役割は文字通り、sceneの中から指定した名前のboneを取得することです。
playgroundではimportmeshでskeleton情報を取得できていますが、今回のarmatureモデルに対して直接スクリプトをアタッチして取得したことが原因かもしれません。

boneの名称はEditorのGraph viewか、Asset browser上のキャラクターメッシュをダブルクリックして開けるMesh Viewerで確認できます。

■Graph Viewの場合
Skeleton confirmation on Graph View of Babylon.js Editor

■Mesh Viewerの場合
Skeleton confirmation on Mesh Viewer of Babylon.js Editor

なお、公式ドキュメントに書いてある通り、単純にアタッチすると位置や向きがずれます。それを防ぐため、attachToBoneを使う前に、boneとswordのvector3の値を0にしています。

If the mesh is far from the origin of the world, then it will appear far from the bone as well which, again, may not be what you want. So before attaching a mesh to a bone set its position to (0, 0, 0) or to a position close to world origin so that the mesh appears close to the bone and appears attached. The position of the mesh in this case simply acts as its offset from the bone.

引用元:Bones and Skeletons | Babylon.js Documentation

        this._leftArmBone.position = new Vector3(0,0,0);
        this._sword.position = new Vector3(0,0,0);

■上記の2つを有効にした場合
Aligned appropriate position of attachToBone in Babylon.js

■上記の2つをコメントアウトした場合
Not aligned appropriate position of attachToBone in Babylon.js

2 particleも合わせて配置するにはisLocalとgravityで調整する

公式ドキュメントではキャラクタの腕に剣や銃を同期させるところまでしか書いていません。今回は剣に炎を纏わせたかったので、particleの向きを調整する必要があります。

以前書いた記事で、剣の刃の部分に沿って炎を纏わせる方法は書きました。

www.crossroad-tech.com

しかし、今回のattachToBoneを使うと、particleの発生方向が同期しなくなりました。

Not syncing particle and sword on Babylon.js Editor

最終的に、試行錯誤しながらisLocalをfalseにしてgravityの値を調整することで、剣を振ったときに炎のparticleが追随するようになりました。

 this._flameParticle.isLocal = false;
"gravity":[0,0,50],  //元はこっちを使用
"gravity":[-10,-30,50],//今回使った値

動作確認結果です。

youtu.be

3 tips

3.1 Blenderにはキャラクタの特定部位と別メッシュの動きを同期させるConstraint機能があるが、Babylon.jsでは未対応

キャラクターの腕の振りに合わせて剣を動かすには、腕と一緒に動く必要があります。方法がわからずにBlenderのforumで聞いてみたところConstraintを教えていただきました。

blender.stackexchange.com

このConstraintを使うことで、自分で指定した位置にSwordを配置してキャラクタアニメーションで使うことができます。

■Constraintを適用する前
Before applying constraint on Blender 2.93

■Constraintを適用した後
After applying constraint on Blender 2.93

Constraintですが、今回はSwordメッシュを選択してから赤枠で囲ったアイコンを選択し、Add Object ConstraintでCopy LocationとCopy Rotationを選択します。あとはそれぞれの値を適当に調整しました。

How to apply and adjust constraint on Blender 2.93

しかし、冒頭で紹介したフォーラムでは「Babylon.jsではconstraintsの機能はない。"trackTo" (constraintの一部の機能) がカメラ関係でサポートされているが、本来のconstraintsの機能はサポートされていない」と回答されています。2018年の投稿ですが、私がみる限り2022年時点でも未サポートのようです。

BJS does not have constraints. The trackTo has a couple applications with exported cameras, but it is converted not supported as a constraint.

引用元:Exporting Blender constraints to BabylonJS - Content creation (3dsMax, Maya, Blender, glTF) - HTML5 Game Devs Forum

ということで今回は使えなかったのですが、参考までに残しておきます。

3.2 attachToBoneでswordの位置が意図と異なる場合、Graph Viewでswordの初期位置や角度を調整するとよい

今回使ったattachToBoneで最終的に動画で紹介したようなことはできましたが、attachToBone適用直後では剣のメッシュが意図しない位置に移動してしまいました。そのため、Babylon.js EditorのGraph ViewでSwordメッシュを選択し、Gizmoのrotationで適当に調整したところ今回の形にできました。GUIで調整できるのは便利ですね。

4. おわりに

だいぶBabylon.jsでキャラクタの動きを作る方法がわかってきました。残りの問題はアニメーションの特定フレームで任意の処理を実行させる方法なのですが、これはもう少し調べてみます。