このブログで使用しているUnityのVer
・Unity 2022.3.19f1
※この記事はUnityちゃんライセンス条項の元に提供されます© UTJ/UCL

ちっす!ゲームをのんびり作ってるえきふるです!
前回の記事で、BlendTreeの超基本的な部分を学びました。
今回はさらに踏み込んだ基本編ということでBlendTreeの深淵、2Dブレンディングの使い方を確認していきましょう!(大丈夫、初心者向けに分かりやすく、丁寧に解説していくので安心して下さい。)

一歩一歩成長していこう
前回に引き続き「ユニティちゃん」の3Dモデルデータとアニメーションデータを使用していきます。
今回の記事ではインストールの方法などは説明しませんので、わからない方、まだ未確認の方は下記をチェックして下さいね。

それでは、やっていこう!
ブレンドツリーの使い方(2Dブレンディング)
ブレンドツリーステートの基本的な作り方、ユニティちゃんの設定の仕方は前回の記事で確認しました。
ここではユニティちゃんモデル、アニメーションがインストール済みでゲームシーンにも入れてあるという前提で、確認していきます。
セットアップ・準備
Animator Contorollerで新規のBlendTreeステートを作成します。

作成したBlendTreeのレイヤー内で BlendTypeを「2D Freeform Directional」にします。

この時、自動でParametor変数「Blend」が作成されている状態ですが「2D」ブレンディングでは2軸を扱うために変数が2つ必要です。
ですのでParameter変数をもう1つ作成(Float型)、2つの変数の名前もそれぞれ「BlendX」「BlendY」と分かり易く変更してあげてください。

これで準備ができました。
アニメーションのブレンド設定
それではアニメーションを実際にブレンドしていきましょう。
BlendTreeのインスペクターからAdd Motionをしてモーションフィールドに項目を8つ追加して下さい。

いきなりめちゃ多いですが、これが2Dブレンディングの醍醐味です。簡単なので安心して下さい。
MotionFieldに追加できたら、Inspector上部のParameters項目で変数を設定する箇所が2つあると思うので先ほど作成した「BlendX」「BlendY」に設定して下さい。

この時、左側が「BlendX」右側が「 BlendY」に設定して下さい。
それぞれの値が下のダイアグラム(ブレンドの様子を視覚化した四角い領域)のX方向(左右)とY方向(上下)の座標になっています。

それでは先ほど作成した8つの項目に「Assets」→「UnityChan」→「Animations」フォルダから必要なモデルデータ内のアニメーションクリップを入れて、PosX、PosYに値を設定していきましょう。

上記画像のように設定していきます。
それぞれのアニメーションクリップの名前と数値の設定は下記。
・WAIT00 PosX=0 Pos Y=0
・WALK00_F PosX=0 Pos Y=0.5
・RUN00_F PosX=0 Pos Y=1
・WALK00_L PosX=-0.5 Pos Y=0
・RUN00_L PosX=-1 Pos Y=0
・WALK00_R PosX=0.5 Pos Y=0
・RUN00_R PosX=-1 Pos Y=0
・WALK00_B PosX=0 Pos Y=-0.5
このダイアグラムのイメージは
キャラクターを上空から見て、正面を上方向(Y方向)とした際にそれぞれの前後左右(必要なら斜めも)の数値の強度に応じてアニメーションの分布をしてあげている感じです。各アニメーションとの距離に応じてブレンド具合が調整されていきます。

それではInspectorのプレビュー画面で実際に挙動を確認してみましょう。
プレビューの再生ボタン(▶︎)を押してダイアグラムの赤丸をグリグリ動かしてみて下さい。

成功です!
前後左右、全方向の動きがそれぞれが上手くブレンドされて滑らかにブレンドしています!

これで世界中を歩き回る3Dアドベンチャーゲームも作れるふるねぇ
これで終わり
…と思いきや、そうです、前回もやりましたがこのままではゲームプレイしても外部から変数を変えられないので動作しません。
そこで次はスクリプトを仕込みます。
スクリプトでBlendTreeの変数をコントロール
今回はキーボードの上下左右で動くようにしました。押している間は数値が上がり、離すと下がります。
実装したスクリプトは下記。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test2DBlend : MonoBehaviour
{
public Animator animator; // Animatorコンポーネントがアタッチされているゲームオブジェクトを入れる
public float acceleration = 1.0f; // 加速度
public float deceleration = 0.5f; // 減速度
public float maxSpeed = 1f; // 最大速度
public float moveSpeed = 2f; // 移動速度
private float speedX = 0f; // 現在のX速度
private float speedY = 0f; // 現在のY速度
// Update is called once per frame
void Update()
{
float targetSpeedX = 0f;
float targetSpeedY = 0f;
// キーボード入力
if (Input.GetKey(KeyCode.UpArrow))
{
targetSpeedY = 1f;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
targetSpeedY = -1f;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
targetSpeedX = -1f;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
targetSpeedX = 1f;
}
// 水平方向の速度を徐々に変化させる
speedX = Mathf.MoveTowards(speedX, targetSpeedX * maxSpeed, (targetSpeedX == 0 ? deceleration : acceleration) * Time.deltaTime);
// 垂直方向の速度を徐々に変化させる
speedY = Mathf.MoveTowards(speedY, targetSpeedY * maxSpeed, (targetSpeedY == 0 ? deceleration : acceleration) * Time.deltaTime);
// Animatorパラメータの更新
animator.SetFloat("BlendX", speedX);
animator.SetFloat("BlendY", speedY);
// キャラクターの移動
Vector3 movement = new Vector3(speedX, 0, speedY) * moveSpeed * Time.deltaTime;
transform.Translate(movement, Space.World);
}
}
わかりにくそうな所だけサッと説明しますね。(スクリプトは本筋ではないので。)
・Mathf.MoveTowards(current, target, maxDelta):
この関数は、currentからtargetへ向かってmaxDeltaの範囲内で徐々に値を変化させます。
current: 現在の値。(ここでは変数speedX)
target: 目標値。(ここではtargetSpeedX * maxSpeed,)
maxDelta: 1フレームでの最大変化量。(ここでは(targetSpeedX == 0 ? deceleration : acceleration) * Time.deltaTime))
・condition ? value_if_true : value_if_false
上記のmaxDeltaの箇所に入れているコード。condition
がtrue
の場合、value_if_true
が返され、condition
がfalse
の場合、value_if_false
が返されます。
※スクリプト内では(targetSpeedX == 0 ? deceleration : acceleration):と記述
targetSpeedXが0の場合はdeceleration(減速度)、0でない場合はacceleration(加速度)を返します。
要はキーが押されていない場合は減速し、押されている場合は加速します。
・transform.Translate(Vector3 translation, Space relativeTo)
この関数で実際のUnityちゃんのワールド上の位置を動かします。
translation: オブジェクトを移動させる量を表す3Dベクトルを入れる。(ここではmovement)
relativeTo: 移動の基準を指定。(ここではSpace.World →ワールド座標系での移動を意味)
それではこのスクリプトをゲームシーンに居るUnityちゃんのモデルにアタッチしましょう。
スクリプトの「Animator」欄にはシーン内のunitychanモデルを入れて下さい。

折角なのでUnityちゃんの移動に合わせてカメラが動くようにモデルのルート直下にCameraを入れて、ついてくるようにしました。

CameraをTPSっぽく背中側の視点に調整。床も移動がわかるようにチェック柄のPlaneを敷いておきました。

では、このスクリプトがうまく動くかゲームプレイ(▶︎)してチェックしてみましょう!

…うん、減速がぬるくて少し微妙な気もしましたが、テストとしては良いんじゃないでしょうか!
しっかり前後左右滑らかに遷移していますね!

これでBlendTreeの具体的な使い方の説明は終わりにしますふる
2Dブレンドツリー項目説明
2Dブレンディングの具体的な方法も確認出来た所で、他のブレンディングに関してもどんなものがあるのか確認してみましょう。
2D Simple Directional

X、Yの2つのパラメータを設定でき、前後左右の歩きモーションなどを作成したい時に便利です。
具体的な使用方法の確認で使った「2D Freeform Directional」と似ています。
ただし、Simpleの方は同じ向きに複数のモーションを並べて置いても中心に近い方のアニメーションしか再生されません。

2D Freeform Directional

「2D Simple Directional」から同じ方向に複数のアニメーションを配置できるようにしたBlendモードです。
具体例でやったように前後左右の歩き→走りの遷移を追加したりするのに便利です。

2D Freeform Cartesian

X、Yの2軸を全く別の概念の軸として使用する場合のBlendモードです。
例として
Xを歩き、後ろ歩き、走りといった前後方向の軸
Yをジャンプの強さ軸
で作成してみました。

イメージ的には横スクロールのアクションゲームで歩き走り中にボタンを押した強さでジャンプの高さが変わるような感じです。
他にも、例えばクトゥルフ系のゲームで各モーションに対して縦軸を狂気度にしてブレンド、とかの方が使うのには適しているような気がします。
TIPS:2D Freeform Directionalとの違い
「2D Freeform Directional」は極座標といって「中心からの角度と強さ」でブレンドを決めていたのに対して、こちらは座標系で「XとYの座標位置」で完全にブレンドを決めているので、同じ変数の値でも結果が違います。
下記は 同じアニメーション配置でX=0.5、Y=0.5 でのモードを変えた場合のプレビュー比較です。


Direct

このBlendモードでは各変数のパラメーターを直接制御します。
2D系のモードではX、Yの2軸でしたがこのモードでは変数は必要な数だけ追加できます。
使い方としてはフェイシャルで「あいうえお」の項目と変数をそれぞれ作り、
セリフに対して口パクを付けて言葉と言葉の繋ぎは自然にブレンドさせるのが良い方法かなと思います。
下記では実際に「AIUEO」の変数を作り、それぞれの変数にフェイシャルの「あいうえお」を登録させて使ってみました。

なお、ここではUnityちゃんアセットデータを使ったフェイシャルの登録の仕方は本筋ではないので割愛。
(もし知りたい方がいたらコメントで言って下さい。)
なお、他のモードとの決定的な違いはブレンドが加算式なので100パーセントを超えること。
今までは100パーセントの値の中で歩きを30%、走りを70%、みたいな感じでウェイトがブレンドされていましたが歩き80%、走り70%みたいな事ができるという事です。

用途に合わせたBlendTypeを選ぼう!
TIPS:BlendtreeのアニメーションにBlendTreeを入れる
ちょっとした小技ですが、実はBlendTreeの中でBlendTreeを登録する事ができます。
「Add Motion」と同じ場所に「Add Blend Tree」という項目があるのでこれを選んであげるだけです。

使い方は例えば、
「Add Blend Tree」でBlendTreeを3つ追加。
2D Freeform Directionalで歩き系のBlendTree、水中で泳いでるBlendTree、乗り物に乗ってる時のBlendTreeをそれぞれ作成します。
それぞれに対して同じダメージモーションをBlendしたいときに2D Freeform Cartesianで横にモーションの種類、縦にダメージモーション、みたいにブレンドして使う事ができます。
試しにUnityちゃんで歩行のBlendTreeとダメージモーションの2つに対してそれぞれジャンプを「2D Freeform Cartesian」でBlendしてみました。

Tree構造は↑こんな感じ。それではプレビューで確認してみます。
なお、歩行アニメーションの中の変数は別にスクリプトで制御するべきですが、
今回はそんなことをしていないので、適当な数値を事前に入れておき、斜め歩行中の想定でやってみました。

こんなイメージです。色々な事に使えそうな機能ですよね。
(まぁ、ジャンプは1回使い切りなんで普通のステートでも良い気がしますけどね…今回は例えってことで)

これでBlendTreeの基本編の説明は終わりふる
終わりに
この記事では、UnityのBlendTreeを使用して複数方向のキャラクターアニメーションをそれぞれ滑らかに遷移させる使い方を紹介しました。次回の記事では、BlendTreeの特殊な使用法について説明してみたいと思います。
もし質問や感想があれば、コメントで教えて下さいね。

コメント貰えると元気も出ますので、どうぞお気軽にお願いしますふる!
◾️Unityアニメーション関連のマトメ記事はこちら
※このブログは、UnityTechnologiesまたはその関連会社が後援または提携しているものではありません。「Unity」は、UnityTechnologiesまたはその関連会社の米国およびその他の国における商標または登録商標です。