Unityを使ったゲーム開発記録

Unityのゲーム開発などを中心に投稿していきます。何か参考になる様な記事ではなく自分用の備忘録になる為、生暖かい目で見て下さい。

Unityでのゲーム開発 〜Blend Tree編〜

Blend Tree

Blend Treeは前回やったAnimatorのモーションとモーションをBlend(混ぜ合わせて)してモーションの近い動き同士で繋ぎ合わせて滑らかな動きを実現できる機能です。

なら前回やった奴も全部Blend Treeで良いじゃんってなりそうですが・・・:(;゙゚'ω゚'):
Transition(遷移)とBlend Treeは区別して実装するのがベターとなっています。

docs.unity3d.com




Blend Treeの作成

作成方法はNewStateと同じく

  • [Create State]⇨[From New Blend Tree]でBlend Treeが作成完了です
  • Blend Treeの作成完了したらダブルクリックをすると編集可能になります

f:id:mochisakucoco:20210324224724p:plain





Blend Treeの編集

f:id:mochisakucoco:20210324225134p:plain

  • ❶はBlend Typeになっていて1Dと2Dの選択が出来ます、今回は1Dタイプを選択しています

⇩⇩ブレンドタイプは下記のリファレンスで確認できます⇩⇩
1D ブレンディング - Unity マニュアル
2D ブレンディング - Unity マニュアル
 

  • ❷はMotionもしくはBlendTreeのフィールドを追加する際に使用します

*BlendTreeの中にさらにBlendTreeを作成する事も可能です
 

*上の画像ではMotionの横の項目の所ですね、チェックボックスにチェックが入っていると灰色になって編集できない様になっているのですぐわかるかと思います。

閾値(しきい値)って何?:(;゙゚'ω゚'):・・・簡単に言うとギリギリの境界線みたいな感じだと思って貰えれば良いと思います。

https://wa3.i-3-i.info/word15001.html閾値の説明はこちらがわかりやすいとおもいます

上の図で説明するのであれば「Idle状態は0~0.4999...まで」、「Walk状態は0.5~1.9999...まで」、「Dash状態は2~」で遷移するモーションの切り変わる境界線とゆうことになります。



今回は上記の内容でMotionとThresholds設定を行いました・・・画像のみで説明とか...楽するな(´-`).。oO


Animatorの初期StateをBlend Treeに変更

今回作成したBlend Treeを初期Stateに変更するやり方を説明します。

  • まずBase Layerで前の画面に戻り
  • Blend Treeの名前をLocomotion[移動とゆう意味]に変更します(分かりやすくする為なので必須ではありません)
  • Locomotionにカーソルを合わせて右クリックで[Set as Layer Default State]にすると初期の状態をLocomotionに変更可能になります。

f:id:mochisakucoco:20210325022128g:plain




Thresholds(閾値)を可変させる為のScript変更

    void Update()
    {

        Horizontal = Input.GetAxisRaw("Horizontal");
        Vertical   = Input.GetAxisRaw("Vertical");

        /// <summary>
        /// 対応したキーを押されたらカメラを切り換える処理
        /// </summary>
        if (Input.GetKeyDown(KeyCode.B))
            {
                aimCamera.SetActive(!aimCamera.activeInHierarchy);
                thirdPersonCamera.SetActive(!thirdPersonCamera.activeInHierarchy);
            }

        /// <summary>
        /// キャラクターが接地している場合の処理
        /// </summary>
        if (isGrounded)
            {
            // 接地したので移動速度を0にする
            velocity = Vector3.zero;
            input = new Vector3(Horizontal, 0f, Vertical);


            // 方向キーが押されている時
            if (input.magnitude > 0f)
                {

                // キーを押されている間の速度(Speed)の変動によってのMotion変化
                var speed = Mathf.Abs(input.magnitude * 2.5f);
                animator.SetFloat("Speed", speed, 2f, Time.deltaTime);

                // 昇れる段差を表示
                Debug.DrawLine(transform.position + new Vector3(0f, stepOffset, 0f), transform.position + new Vector3(0f, stepOffset, 0f) + transform.forward * slopeDistance, Color.green);

                // ステップ用のレイが地面に接触しているかどうか
                if (Physics.Linecast(stepRay.position, stepRay.position + stepRay.forward * stepDistance, out var stepHit, LayerMask.GetMask("Field", "Block")))
                    {
                    // 進行方向の地面の角度が指定以下、または昇れる段差より下だった場合の移動処理
                    if (Vector3.Angle(transform.up, stepHit.normal) <= slopeLimit 
                        || (Vector3.Angle(transform.up, stepHit.normal) > slopeLimit 
                        && !Physics.Linecast(transform.position + new Vector3(0f, stepOffset, 0f), transform.position + new Vector3(0f, stepOffset, 0f) + transform.forward * slopeDistance, LayerMask.GetMask("Field", "Block"))))
                    {
                        velocity = new Vector3(0f, (Quaternion.FromToRotation(Vector3.up, stepHit.normal) * transform.forward * walkSpeed).y, 0f) + transform.forward * walkSpeed;
                        Debug.Log(Vector3.Angle(transform.up, stepHit.normal));
 
                    } else {
                        velocity += transform.forward * walkSpeed;
                    }
 
                    Debug.Log(Vector3.Angle(Vector3.up, stepHit.normal));
 
                // 地面に接触していない場合
                } else {
                    velocity += transform.forward * walkSpeed;
                }
            // キーを押していない場合は移動しない
            } else {
                animator.SetFloat("Speed", 0f);
            }

            // ジャンプの処理
            if (Input.GetButtonDown("Jump")
                && !animator.GetCurrentAnimatorStateInfo(0).IsName("Jump")
                && !animator.IsInTransition(0))      // 遷移途中にジャンプさせない条件
            {
                animator.SetBool("Jump", true);
                // ジャンプしたら接地していない状態にする
                isGrounded = false;
                velocity.y += jumpPower;
            }
        }
    }

  • void Update()部分に変更を加えています
  • 前回のAnimator編で説明していませんでしたが[animator.Set〇〇("〇〇");]と付けるとAnimatorを呼び出せます・・・oi

*Setの後ろの〇〇はAnimatorで設定したparameter値[Float,Bool,Int,Trigger]を入れます[ " " ]で囲っている〇〇の中はparameterの名前です



void Update()
    {

      〜〜

     // キーを押されている間の速度(Speed)の変動によってのMotion変化
     var speed = Mathf.Abs(input.magnitude * 2.5f);
     animator.SetFloat("Speed", speed, 2f, Time.deltaTime);

      〜〜
  • Mathf.Abs(input.magnitude * 2.5f);でキーが押されている間2.5fになるまでの絶対値を指定して
  • animator.SetFloat("Speed", speed, 2f, Time.deltaTime);でanimatorの呼びだし条件に上記の内容を2fごとに呼び出す様にしています。

*ここの2fの所を0に近づける事に変動率が早くなる為、遷移させたいMotionごとに設定で調整するとよく見えると思います。

BlendしたMotionがこちら⇩⇩

f:id:mochisakucoco:20210325143306g:plain
分かりずらいですが、歩くMotionからDashまでの繋ぎが滑らかになっています。


Motionの可変をUPにした物

f:id:mochisakucoco:20210325145558g:plain






今回はここまで




f:id:mochisakucoco:20210325162029g:plain
あら・・・あなた空中走ってません_:(´ཀ`」 ∠):
そんな訳で次回は細かいAnimatorの設定を終わらせたいと思います