【Unity】ジャンプと落下にモーションをつける

いろいろと移動処理を作ってきたのですが、
移動ができるとアクションにモーションを設定したくなってきます。

今回は、アクション系なら欲しいモーション
ジャンプと落下のアニメーション連動を考えていこうと思います。

長い間、ブログの更新と勉強をお休みしていたのですが、
その辺りは無かった事にして、シレっと続きを書いていこうと思います。
ダメダコリャ!( ~っ~)/ σ(^_^;)


さて、ジャンプと落下のモーションを作るって事なんですが、
まず床を走っている状態を作ります。

アニメーションのお勉強(IK編)で作った走るモーションを使います。
Linecastの設定は端折るので、共に過去記事を参考にして下さい。
ActionTest

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ActionTest : MonoBehaviour
{
[Header("レイヤーマスク")]
public LayerMask floorLayer;

private Rigidbody2D playerRB; //Rigidbody取得
private Animator motion; //Animator取得

private float runSpeed = 0f; //走るスピード
private bool jump; //ジャンプフラグ
private const float jumpPow = 400f; //ジャンプ力

private const string CLIP_KEY="Action"; //Animatorの変数名

private bool bodyUnder; //体下Ray

//アクションナンバーの設定
private enum actionNum
{
stop = 0,
run = 1,
jump = 2,
fall = 3,
}

// Start is called before the first frame update
void Start()
{
motion = GetComponent<Animator>();
}

// Update is called once per frame
void Update()
{
SetLinecast();

if (bodyUnder)
{
runSpeed = 10f;
AnimationChange(actionNum.run);
}
}



//アニメーション切り替え
private void AnimationChange(actionNum num)
{
motion.SetInteger(CLIP_KEY, (int)num);
}

//Linecastは過去記事を参照下さい。
//床との接触判定はbodyUnderフラグに取っています。
}

SetLinecast()メソッドはLinecastの取得メソッドです。

SetLinecast()で床との接触判定をbodyUnderに取得して、
trueなら走るアニメーションを再生します。

これで床に着地すると走りだします。

ベースになるモーションが設定できたので、
ジャンプ処理を追加します。
ActionTest

// Start is called before the first frame update
void Start()
{
playerRB = GetComponent<Rigidbody2D>();
motion = GetComponent<Animator>();
}

// Update is called once per frame
void Update()
{
SetLinecast();

if (bodyUnder)
{
if (Input.GetKeyDown(KeyCode.UpArrow))
jump = true;

AnimationChange(actionNum.run);
}
}

private void FixedUpdate()
{
playerRB.velocity = new Vector2(runSpeed, playerRB.velocity.y);

if (jump)
{
playerRB.AddForce(Vector2.up * jumpPow);
jump = false;
}
}

床に接触している時だけジャンプできるようにしたいので、
bodyUnderフラグ判定内にキーコードを仕込んで、
上矢印キーを押すとジャンプするようにしました。

ジャンプが実装できたので、アニメーションを作成します。
モーション①.png
キーフレームは0秒にジャンプ中の姿勢を用意するだけでOKでっす。
IKが組み込まれていると走っている形からジャンプの形まで手足が動いてくれます。

アニメーター画面に切り替えて、
モーション②.jpg
パラメータにint型のActionを設定します。
新しく出来たJumpクリップにRunクリップからトランジションを設定します。

設定したトランジションを選択して、インスペクターから
モーション③.jpg
終了時間ありのチェックを外して、パラメータに2を設定しておきます。

これでクリップ遷移が準備できたので、
スクリプトの作成となるんですが…

ジャンプ時の遷移をどのタイミングで取るかを考える必要があります。

当然、上矢印キーを押した所で呼び出せばと思うのですが、
キーを押す判定の中で呼び出してもクリップの遷移が起きないんですよね~(T^T) ヒック

Input.GetKeyDown(KeyCode.UpArrow)を使うと一度だけ処理が行われます。
この一度の処理では、アニメーションの切り替えが呼び出されないんですよ。

Update内でAnimationの切り替えを行う場合、
条件に合致した状態をキープしておかないと、
なぜかAnimationの切り替わりが行われません。

keycodeは、一度の呼び出しだけなので、無反応になります。
なので確実に呼び出せるFixedUpdate内で呼び出します。
ActionTest

private void FixedUpdate()
{
if (jump)
{
playerRB.AddForce(Vector2.up * jumpPow);
AnimationChange(actionNum.jump);
jump = false;
}
}

おそらくUpdateでInput.GetKeyDownを処理すると
Animationの切り替えがコマ落ちと言うと変ですが、処理が追い付かないのでは?
と思っています。

FixedUpdateだと定期で安定しているので、確実に呼び出したい場合は、
こちらに処理を設定する方が問題ないかと思います。

これでジャンプのモーションができるようになったので、
落下モーションを作っていきます。

Animationを開いて、
モーション④.jpg
落下の姿勢を0秒に登録します。

続いてAnimatorに切り替えて
モーション⑤.jpg
Jump→Fall、Run⇔Fallのトランジションを設定します。

この時の注意点が二つあって、一つ目が
Runとfallはどちらにも遷移できるようしておくって事です。
なぜかと言うと、床の切れ目なんかで落下する際、Runからfallに繋げてないと
Animationの遷移が行われないので、走ったまま落下していきます。

もう一つの注意点は、
今回は、JumpからRunに遷移を用意してない事です。
JumpからFallに遷移してRunに戻るように設定しているので、
Jump中に床に着地してもRunに戻りません。

Jump中?となりますが、
落下モーションを入れてるので、Jumpが上昇、Fallは落下と分けています。
なので上昇中に床に着地してもRunクリップに遷移が起こりません。

この辺りは、状況に合わせてトランジションを追加すればOKかと思います。

各トランジションの設定は、
モーション⑥.jpg
JumpからFallは、Actionを3に設定しておきます。

FallからRun
モーション⑦.jpg
パラメータは、1です。

RunからFall
モーション⑧.jpg
パラメータは、3です。

クリップの遷移が設定できたので、スクリプトを組んで行きます。
ActionTest

// Update is called once per frame
void Update()
{
SetLinecast();



if (bodyUnder)
{
runSpeed = 10f;

if (Input.GetKeyDown(KeyCode.UpArrow))
jump = true;

AnimationChange(actionNum.run);
}
else if (playerRB.velocity.y < 0)
AnimationChange(actionNum.fall);
}

まず落下と言う事で床に接触してないのが条件になります。
なので、bodyUnderフラグがfalseの時に落ちている判断をします。

キャラの状態が上昇・下降・停滞を判断するには、
RigidbodyのvelocityのY軸を見れば判断できます。

velocityは移動する方向のスピードなんですが、
落下の場合、Y軸がマイナスに加速されて行きます。

なので、キャラのvelocity.y がマイナスになっていれば落下している事が分かります。

あとは、落下判定内にアニメーションの切り替えを仕込んでおけば、
落下中ならクリップの遷移が行われます。

ちなみに床の接触判定をからめていますが、この処理をしておかないと
坂を設定したりすると、下りの時に落下モーションが呼び出されてしまうので、
必要になるかと思います。

これで一通りの処理が完成したのでPLAYしてみます。

移動量が少ないので、ちょっと分かりにくいでしょうか。

一応、狙いのモーションを設定する事ができました。

ただ、この動画では分かりにくいのですが、
Jumpモーションの踏み切りで若干の違和感があります。

左足で踏み切ったモーションにしてるので、
走ってる時、左足が前にある所でジャンプすると、
飛び上がってから左足を後ろに踏み蹴る感じになります。

この違和感は、今後の課題として修正案を考えてみたいと思っています。

最後にJumpクリップの呼び出し方法として、
velocityを使って、クリップの遷移方法もあります。
ActionTest

void Update()
{
SetLinecast();



if (bodyUnder)
{
runSpeed = 10f;

if (Input.GetKeyDown(KeyCode.UpArrow))
jump = true;

AnimationChange(actionNum.run);
}
else
{
//落下中なら
if (playerRB.velocity.y < 0)
AnimationChange(actionNum.fall);
//ジャンプ中なら
else if (playerRB.velocity.y > 0)
AnimationChange(actionNum.jump);
}
}

velocityがプラスに加速されたらジャンプと判断するって感じです。

今回は、キー操作でジャンプ開始を判断できたので、
キーを押すタイミングでクリップ遷移すればOKだったんですが、
ジャンプ台やトランポリンのように強制ジャンプの場合、
遷移のタイミングがとりずらいので、
velocityから読み取ると自動的にジャンプモーションを呼び出す事ができそうです。

ジャンプと落下のモーションについては以上となります。
モーション処理の参考になれば幸いです。

次回は、スライディングの処理を作れたら記事にしてみようと思います。
それでは、・・・・・・・・~~~ヽ(^◇^))) ほな、さいなら!

この記事へのコメント