今回のUnityテーマは、「Animator Controllerを作成して立ち・移動・攻撃・ジャンプ アニメーションを実装する方法」です。
ある程度、アセットなどを使って動作させられるようになってきたら、次は自分好みの動きをキャラクターにさせてみたいと思う様になると思います。
この記事では、アセットなどで用意されている「Animator Controller」ではなく、コントローラーを自作することでオリジナルのアニメーションコントローラーを作成できる技術を身に着ける方法を紹介します。
少し長くなってしまうので、複数回に分けて紹介します。
開発環境と前準備
この記事では以下の開発環境を利用します。
合わせる必要はないですが、合わせることによって同じ画面になります。
開発環境
・Unity 2020.3.30f1
・Visual Studio 2022
使用アセット Unityちゃん
また、キャラクターモデルのアセットとして、Unityちゃんアセットを利用します。

使用モーション mixiamoからダウンロード
無料で3Dやアニメーションのダウンロードできるmixamoのアニメーションを利用します。
・Action Adventure Packをダウンロードしておいて下さい。

mixamoサイトの使い方は以下の記事で紹介していますので、初めて利用する方はあわせて確認してみて下さい。

Unityでの前準備 インポートと地面の作成
3Dのプロジェクトを作成し、上記で紹介したアセットやモーションをインポートしておいて下さい。
- Unity chan アセット…アセット取得後、Package Managerよりインポート
- mixamoのAction Adventure Packを解凍してフォルダごとドラッグアンドドロップでインポート
また、キャラクターを動かせる場所を作成します。Hierarcyより、「+>3D Object>Plane」で地面を作っておいて下さい。

Animator Controllerのセットアップ
キャラクターの配置とAnimator Controllerの作成
まず、Unityちゃんを画面上に出現させます。
何もついていないUnityちゃんを利用したいので、「Project>Unity-chan!>Unity-chan! Model>Art>Models」より、「unitychan」を「Scene」にドラッグアンドドロップして出現させます。そのままだとカメラと逆に向いているので、Transform>RotationからYを180にしてカメラの方に向けておきます。


階層を「Project>Assets」に移動して、右クリック>Createから「Animator Controller」を作成します。名前はなんでもいいので今回は「PlayerController」にします。

Unitychanをクリックして、インスペクターのAnimator>Controllerに先程作成した「PlayerController」をドラッグアンドドロップします。
そして、「Apply Root Motion」のチェックを外して、Update Modeを「Normal」にしておきます。

Avatarは既に設定されているため、今回はそのまま利用します。
Avatarについて詳しく知りたいという方は以下の記事を併せて確認下さい。

立ちモーションの実装
Animator Controllerに立ちモーションを実装します。
「mixamo」でダウンロードしてインポートした「Action Adventure Pack」の中から「idle(2)」を探してインスペクターを確認します。
※idle(2)にした理由は、足が動かないからです。待機モーションで足が動くとややこしいことになるので、今回はidle(2)を使って説明します。
「Animation」の名前が mixamo.comになっているので、「idle2」に変更します。また、立ちモーションはループさせたいモーションなので、「LoopTime」「Loop Pose」にチェックを入れます。修正後、一番下の「Apply」を押して確定します。

また、「Rig>Animation Type」を「Humanoid」に変更しApplyを押して確定しておきます。

次に、先程作成した「PlayerController」をクリックして、Animatorタブを確認します。
Animatorタブがでていない場合は、「Window>Animation>Animator」から表示することができます。
Animatorの画面に、先程修正したidleをドラッグアンドドロップします。すると、Entryからidleにトランジションの線が伸びます。

再生して動作を確認してみます。

立ちモーションの実装ができました!
移動モーションの実装
物理演算(RigidBody)の付与
unitychanのインスペクターから「Add Compornent」から「Rigidbody」を付与します。


プレイヤーの移動のスクリプトの作成
移動モーションを作成する前に、移動のためのスクリプトを作成します。
「Project>Assets」に右クリックからフォルダを作成し、フォルダ名を「Scripts」とします。
Scriptsフォルダの下に、右クリックから「Create>C# Script」でファイルを作成し、ファイル名を「PlayerControllManager.cs」とします。
これを「unitychan」のインスペクターへドラッグアンドドロップして読み込みます。

「PlayerControllManager」をダブルクリックして、エディタを開きます。
以下のスクリプトのように修正します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControllManager : MonoBehaviour
{
//移動速度
[SerializeField] float moveSpeed = 2;
private float x; //横方向の移動
private float z; //奥方向の移動
private Rigidbody rb;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
//■キーボード入力を取得
x = Input.GetAxisRaw("Horizontal"); //横方向の取得
z = Input.GetAxisRaw("Vertical"); //奥方向の取得
}
private void FixedUpdate()
{
//横方向の速度設定
rb.velocity = new Vector3(x * moveSpeed, 0, z * moveSpeed);
}
}
以下のようなスクリプトになります。
- Startで「Rigidbody」で取得
- Updateでキーボード入力を取得
- FixedUpdateでキーボードで取得した方向に移動速度を1で取得したrigidbodyへ設定
- 移動速度は、moveSpeedで変更可能。[SerializeField]に設定しているので、インスペクターから変更が可能です。
これで移動のスクリプトができました。一度動作を確認してみましょう。

走るアニメーションの設定
まずは、「idle2」と同じようにアニメーションの設定を行います。「Action Aventure Pack」の「running」を探してクリックします。
インスペクターから「idle2」と同様に、「running」Rigの「Animation Type」を「Humanoid」に、「Animation」の「LoopTime」と「LoopPose」にチェックを入れてApplyを押します。
「PlayerController」の「Animator」を開いて「running」をドラッグアンドドロップで配置します。
動作を確認したいので、一度、「Idle2」から「running」へ繋ぎ変えます。
「running」を右クリックして、「Set as Default State」をクリックします。

再生して動作を確認してみます。

動作の確認ができたので停止して、Animatorのを「Idle2」に右クリックから「Set as Default State」を使って戻しておきます。
アニメーションの切り替え
「Idle2」から「running」にトランジションしてほしいので、「Idle2」で右クリックをして、「Make Transition」をクリックして、「running」と繋ぎます。
次に、「running」から「Idle2」へトランジションする場合もあるので、「running」で右クリックして「Make Transition」をクリックして「Idle2」へトランジションを繋ぎます。

トランジションの設定をしていきます。「Idle2」から「running」へ伸びている矢印をクリックします。
インスペクターにトランジションの設定が表示されます。「Conditions」の設定を増やすために、先に「Animator」の「Parameters」からパラメータを追加します。
「Prameters>+>Float」でパラメータを追加し、名前をSpeedとします。

次に「Conditions」の設定を追加します。「Conditions>+」で追加し、
「Speed : Greater : 0.01」と設定します。これは、Speedが0.01より大きい場合に遷移するという意味になります。

さらに Has Exit Timeのチェックを外して、その下のSettingsの中の「Transition Duration(s)」を0にします。

- Has Exit Time…これにチェックが入っている場合、前回のアニメーションが終了するまで待機します。
- Transition Duration…遷移時間を指定できます。
次に、「running」から「Idle2」へのトランジションの設定を行います。矢印をクリックして、先程と逆の設定を施していきます。
「Conditions」を追加して、「Speed:Less:0.01」という設定にします。これは、Speedが0.01未満の場合という意味になります。

また、先程と同様に、「Has Exit Time」のチェックを外して、「Transition Duration」を0にしておきます。
これでトランジションの設定ができましたので、動作を確認していきます。AnimatorのタブがSceneと同じ配置にしていると確認し辛いので、Animatorのタブを別の場所に移動させて動作確認します。

再生して、Animatorの数値を手動で変更すると動作の切り替わりを確認することができます。

スクリプトからアニメーションと移動の連動をさせる
先ほど作成した「PlayerControllerManager」スクリプトを、Animator Controllerの値を取得してパラメータ「Speed」の値を変更できるように修正します。
「PlayerControllerManager.cs」をダブルクリックでエディタを開いて以下のコードに修正します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControllManager : MonoBehaviour
{
//移動速度
[SerializeField] float moveSpeed = 2;
private float x; //横方向の移動
private float z; //奥方向の移動
private Rigidbody rb;
private Animator animator;
// Start is called before the first frame update
void Start()
{
//リジッドボディコンポーネントを取得
rb = GetComponent<Rigidbody>();
//animatorコンポーネントを取得 //追加!
animator = GetComponent<Animator>(); //追加!
}
// Update is called once per frame
void Update()
{
//■キーボード入力を取得
x = Input.GetAxisRaw("Horizontal"); //横方向の取得
z = Input.GetAxisRaw("Vertical"); //奥方向の取得
}
private void FixedUpdate()
{
//横方向の速度設定
rb.velocity = new Vector3(x * moveSpeed, 0, z * moveSpeed);
//Animator Controllerからパラメータを取得する //追加!
animator.SetFloat("Speed", rb.velocity.magnitude); //追加!
}
}
animatorコンポーネントの取得と、そのanimatorコンポーネントのパラメータに対して「SetFloat」を使って、パラメータ「Speed」の値を変更するスクリプトに修正をしました。
再生して動作確認してみます。

これで動いているときに、runningモーション、止まっているときにidle2のモーションに切り替わるようになりました。次に、移動方向への向き変換を実装します。
移動時の向きの変更
今までは、常に前向いて移動していたので、移動方向変更時に進む方向へ向きを変更するように修正をかけます。
「LookAt」関数を利用して方向を変更していきます。
LookAt(X)…Xの方向を向く。
「PlayerControllManager」を、以下のスクリプトに修正します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControllManager : MonoBehaviour
{
//移動速度
[SerializeField] float moveSpeed = 2;
private float x; //横方向の移動
private float z; //奥方向の移動
private Rigidbody rb;
private Animator animator;
// Start is called before the first frame update
void Start()
{
//リジッドボディコンポーネントを取得
rb = GetComponent<Rigidbody>();
//animatorコンポーネントを取得
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
//■キーボード入力を取得
x = Input.GetAxisRaw("Horizontal"); //横方向の取得
z = Input.GetAxisRaw("Vertical"); //奥方向の取得
}
private void FixedUpdate()
{
//横方向の速度設定
rb.velocity = new Vector3(x * moveSpeed, 0, z * moveSpeed);
//Animator Controllerからパラメータを取得する
animator.SetFloat("Speed", rb.velocity.magnitude);
//方向の取得
Vector3 direction = transform.position + new Vector3(x, 0, z); //追加!
//向きの変更
transform.LookAt(direction); //追加!
}
}
LookAtを使って、現在位置から移動方向への座標を向くように修正しました。
動作を確認してみましょう。

入力方向へ方向転換することが確認できました。
※今回の例では、入力方向へ急に方向転換してしまいます。滑らかに方向転換させようとすると回転を計算させる仕組みが必要になり複雑になってしまうので今回は割愛します。
攻撃とジャンプ
記事が長くなってしまったので第二回目の記事で紹介します。
※執筆中
まとめ
今回は、「Animator Controllerを作成して立ち・移動・攻撃・ジャンプ アニメーションを実装する方法」の「立ち・移動」までの実装を紹介しまいた。
- Animator Controllerのセットアップ
- 立ちモーションの実装…Animator Conttrollerで実装
- 移動モーションの実装…Animator Controllerのパラメータやトランジションの設定
- 方向転換…LookAtを使った回転
慣れていないと大変だったと思いますが、実装した内容は意外とシンプルだったのではないかと思います。
次の章で攻撃とジャンプを実装していきます。もう少しなので第二回目も頑張りましょう!
今回の記事が、皆さんの技術力向上につながると嬉しいです。
もしこの記事が気に入りましたら、ぜひテクリエイトへのブックマーク登録をして頂けると喜びます。
以上、おつかれさまでした!

© Unity Technologies Japan/UCL