自然なジャンプをしてほしくて-Unityでジャンプアニメーションをいじいじする-
Unityで自然なジャンプを目指したあるみにの話。
一年前くらいに頑張った事を再現しつつまとめておく記事。
- 3Dキャラクターを動かすゲームを作りたい!
- 目標
- とりあえず移動とカメラ
- ジャンプ実装
- ジャンプしてないよ
- 不自然だよ
- 切り刻もう、ジャンプモーション。
- 切り刻んだジャンプモーションたち
- いざ改修
- アニメーションイベントってすごくね?
- モーションに合わせて当たり判定を伸縮させる
- まとめ
- ライセンス
3Dキャラクターを動かすゲームを作りたい!
せっかくならばキズナアイちゃんに動いてもらいたいところですね。
アニメーションを仕入れるためにもアセットの力を借りよう。
……ということでUnityちゃんアセットから色々持って来てみる
一度Unityちゃんに元からある移動スクリプトで動かしてみよう。
動いてくれたね。
上キーで進み、左右キーはその場で止まって方向転換するみたい。ちょっと使いにくい。
カメラの視点を背面に固定すれば(もともとはそうなっている)違和感がないのだけど。
他のアセットの移動スクリプト、、例えばいつかの記事の「とりあえず操作する編」のものを使ってもいいのだけど、
自由に機能を追加しようとすると元々のスクリプトを完全に理解して改変する必要があるので、
なかなか闇が深くなってしまいそう、、、、
今のレベルで読み解くのは難しいので、移動スクリプトも一から書いていこう。
目標
三人称視点とはいえ、ただ後ろにカメラが周りこんでくるだけなのは少し寂しいので、プレイヤーがカメラを操作するやつをやりたい。
あとは人間的で自然な動き……これが大変そうな気がしますね()
とりあえず移動とカメラ
と、いうことで自分たちで、一連のスクリプトを書いてきました。
”たち”、というのは、3Dキャラを動かしてゲームを作ろうとしている過程で、友人を1人巻き込んでペアプロジェクトのようなものをしているためです。
その話はまあおいおいしていきたい。(そういうのを書いていくべきなんじゃないですかね)
ともかく3Dキャラを動かす勉強だって事で、いろいろ調べつつ移動スクリプトを書きました。
こんな感じになりました。
マウス操作で視点をグルグルいじりながら、WASDキーで移動するものです。
移動&カメラ処理について
ChatracterContolloerを使った移動は自分が、カメラ処理は友人が主に書いてくれました。
カメラ移動はそのカメラの正面を軸に、WASDで移動になるようにお互いにかみ合わせたのがアピールポイントですかね?
まあそうじゃないとカメラに対して反対向きのときは行きたい方向と逆に入力しないといけないだとか、おかしいことになりますからね。
一番はじめのUnityちゃんの移動スクリプトは、カメラの位置にかかわらず、上キー入力でその時向いている方向へ進むので、
ただの三人称視点カメラでは操作しているうちにどんどん感覚がずれてくるという問題がありました。
何度も言う通りカメラが基本的にUnityちゃんの後ろにまわる事が前提のスクリプトだったわけですね。
かみ合わせたといっても、カメラの正面方向と入力方向のベクトルと掛け合わせたものを実際の移動に使ってるだけですが、、、
お互いググりながらとはいえ、カメラをグリングリン動かす方が大変な気がするので友人に感謝。
今はお互いにこの手の実装はできるようになりました。多分。
グリグリカメラ移動、いいですねえ
ジャンプ実装
というかここからが本題なんですが。
今のでカメラに関する目標はほとんど達成されたとみていいでしょう。
あとは操作面でどれだけ"人間的にできるか"ということになりそうです。
ということで実際のジャンプに移りたいわけですが、これもUnityちゃんのジャンプモーションがあり、これを使ってみるわけですよ。
この感じだとうまくジャンプできている気がするが、、、
ジャンプしてないよ
これ、ジャンプしてません。
どういうことかというと、これ、ジャンプのモーションだけ再生して判定は跳ねてないんです。
こういうことです。
これだど当たり判定が残ったままなので、障害物を乗り越えるということがまるでできないですね
まあこれは、ジャンプ時に上方向の力をこちらで付ければいいだけなので、やってみる。
不自然だよ
おわかりいただけただろうか……
そうこれ、ジャンプの入力とともに上方向の力を与えただけなんですが、
ジャンプの予備動作から飛んじゃってる。
もっというと、
着地モーションと全くあっていない。
というね。
実はこの問題、一番はじめのUnityちゃんのときから既に垣間見えていたんですよ。
これとか。モーションが早く終わって空中に着地して空中を走ってますね。
さらに言えば、着地モーション中に移動できてしまうので足を動かしてないうちに滑るように移動してしまったりしてしまってます。
うーーん不自然。
これらを解決するためにどうしたらいいのか。
予備動作を切り取って、着地モーションも切り取るかすぐに移動に遷移させれば見栄えは解決するかもしれない。
ジャンプモーションに合わせて当たり判定を動かしたり、加える力を調整したらいいかもしれない。
しかし、これからジャンプの高さは調整できるようにしたい。
もしトランポリンに乗せるとか、能力上昇のために倍率をいじるのであれば、
当たり判定に合わせてモーションは再生されるべきでしょう。
そして、予備動作とかも再生した人間的な部分を再現しておきたい。
どうしようか……
…………
……
…
ジャンプモーションを切り刻もう。
切り刻もう、ジャンプモーション。
ググる力が弱いのか、有効そうな策を見つけられなかったあるみにの苦肉の策です。
問題は、ジャンプモーションが予備動作、ジャンプから着地まで一つのアニメーションになってるのが問題なんですよ。
とはいえ、自分に着地モーションを作ったりする技術はいまのところ持ってない……
いや、着地モーション、ありますね、そこに。部分に。
ということです。
はいUnityちゃんのジャンプモーションである、「unitychan_JUMP00B」をいくつか切り分けで保存してみました。
同じアニメーションから、元々のアニメーションも合わせて10個のAnimationClipがあります。
StartとEndの標記のおかげでわかりやすくなってるのだが、状態に合わせて時間で区切って作っています。
10個ありますが、最終的には4つくらいしか使ってないんですけどね()
使ってる奴だけ紹介しましょう。
切り刻んだジャンプモーションたち
まず、ジャンプをはじめる「JampStart」です。
次に、滞空アニメーション(上昇中)の「Jump04」です(名前つけろ)。
そして落下モーションの「Fall」です。
最後に、着地モーションの「Jump07」です(Landingとかにしろ)。
これらを一連で再生すれば、元のジャンプアニメーションになります。
これらを状況にあわせて制御することで自然なジャンプアニメーションを表現するもくろみです。
いざ改修
まず、以前のジャンプアニメーションのアニメーションコントローラーがコチラ。
シンプルですね。
そして次、自然なジャンプアニメーションを目指したアニメーションコントローラがコチラ。
デデドン。
一気にStateが増えて遷移する矢印も入り組んできました。
実際に実行するとこんな感じです。
さっきと同じだけの力でジャンプさせてますが、かなり安定した見栄えになってるのでは??
簡単に言うと、ジャンプ開始アニメーションのあと、上昇アニメーションにはいり、
キャラのy方向の速度が負の値になる=落下するときに落下モーションに変更、
地面を検知したときに着地モーションを再生する。
と、いう感じです。
サラッと言ってますがコードのほうは70行くらい増えました。
具体的には、床の判定をより正確にとるために、下方向にレイを飛ばすことにしたのと、
各状態が整合性をもって遷移できるように条件分岐を書いたりしました。
コードとかも載せた方がいい……と思うのだがうまい載せ方を考える気力がないので、また別で紹介するか、GitHubで紹介するかもです。
(いまのはキズナアイとかいるので簡単に公開できないというアレ)
おかげで、かなり汎用性のあるモーション再生ができている気がします。
例えば、ジャンプ地点と着地地点の高さが異なっても、違和感ないのがいいですね
また、副産物的に落下モーションだけを使って、「ある程度の高さから落下した場合落下モーションをする」こともできるようになりました。
アニメーションイベントってすごくね?
もうひとつ、予備動作はそのままでモーションで跳ねたときに合わせてジャンプができてます。
これはアニメーションイベントを使いました。
ジャンプモーションのうち、跳ね始めである「JumpStart」のアニメーションのインスペクターから、「Events」という項目を開くことができます。
上の写真では、タイムライン上にJumpStartと表記された場所があると思います。
アニメーションイベントとはアニメーションの進行中に設定した関数を呼ぶ事ができる機能です。
つまり、跳ねる瞬間の時点で「上方向に力を加える処理」を登録すれば、そのタイミングでアニメーションがその処理を呼んでくれるわけです。
↑跳ねるタイミング、、、、ココ!!!!!
それから、最後の着地モーションにまだ滑っていたので、一定の時間移動処理しないようなアニメーションイベントを追加しておきました。
ジャンプ中も入力しっぱなしにしてます。比較すると分かりやすい。
モーションに合わせて当たり判定を伸縮させる
ジャンプ中、体を反るアイちゃんですが、足を上げて乗り越えられるようにみえるブロックが乗り越えられない。
それもそのはず。当たり判定自体はしっかり引っかかっているのだ。
ということで、ジャンプモーション中の体の"そり"に合わせて当たり判定が伸縮するようにもしてみたりしました。
アニメーションイベントのときと同じ要領で、
ジャンプモーションのうち、反ってる「Jump04」のアニメーションのインスペクターから、「Curves」という項目を開くことができます。
ここでは特定の変数に対して、アニメーションの進行に合わせて値を変化させられます。
ここに当たり判定の大きさを決める三要素に対応する変数を作り、モーションに合わせて伸縮するように値を設定。
上の写真のように値がグラフのような変化をしてくれます。
ここの変数はAnimationControllerに対応するので、移動スクリプトから読み出して当たり判定に実際に適応させるようにします。
これならば実際に乗り越えられますね。
乗り越えられました。
一応、当たり判定の変化の様子を載せておく。
かなりジャンプは突き詰められたかな。
まとめ
移動スクリプト、もといジャンプを自然に見せるためにいろいろしてみました。
個人的にかなり完成度の高いものにできたのではないかなーと思っています。
でも、実際この解決法って、どうなんだろう?
けっこうな力技である気がしないでもないし、もっとうまい方法があったのかも……
そんな情報をお持ちの方がいましたら是非教えて頂きたいです。
ヒントだけでも()
今回、GIFをいっぱいつかうというのが裏目標みたいなところがあったんですが、
わかりやすくなってましたかね、、
あとはコードを載せるか否かというところは、まあおいおい追加するかもしれない
自分が必要な部分だけ思い出せるようになるかもしれないし。
もっと具体的な実装方法もいずれ述べるかもしれない。
いままでで一番開発ブログという感じのする記事になったかなと思うので、
これからも記事をかきつつ開発を進めていきたいですねえ
まあ今回の内容、一年前くらいにやってたことなんですけどね。
状況再現なんかやったりしたので、色々思い出せてよかったです。
これからも過去にやった事とか新しくやる事をどんどん記事にしたいぞ
ライセンス
Unityちゃん
http://unity-chan.com/contents/license_jp/
このコンテンツはユニティちゃんライセンスより提供されています。
(c)Kizuna AI