Parallels Desktop 15%OFF クーポン

【Unity】タワーディフェンス(5) 敵の移動アニメーション【クソゲー制作】

タワーディフェンスを作る(5)

Unity初心者が2Dタワーディフェンスを作っています。今回は敵の移動方向に応じてアニメーションを切り替える処理を実装します。

環境
  • Mac mini (M1, 2020)
  • Unity 2022.3.36f1
目次

左、上、下方向のアニメーションの作成

敵が右方向へ移動するときのアニメーションは前回作成済みです。同じ手順で左、上、下方向へ移動するときのアニメーションを作成します。

なお、以下のようなキャラチップをインポート済みで、これらを使ってアニメーションを作成します。

タワーディフェンス45
  1. 敵画像のslime_leftslime_walk_leftをまとめて選択してヒエラルキービューにドラッグ&ドロップします。
  2. 「Create New Animation」ウインドウが開くので「Assets/Animations」フォルダ下に名前を「Enemy0_left」にして保存します。
  3. ヒエラルキーに「slime_left」という名前のオブジェクトが作成されるので、インスペクターの「Sorting Layer」「Object」に変更します。これでオブジェクトが最前面に表示されます。
  4. このオブジェクトのAnimationビューで「Samples」の値を2に変更します。これはアニメーションの速度の設定です。再生ボタンを押してアニメーションを確認しましょう。
  5. ヒエラルキーのオブジェクト「slime_left」は削除します。アニメを作成するために作ったものなので、もう用済みです。

以上の手順で上方向のアニメ(slime_up)と下方向のアニメ(slime_down)も作成します。

「Assets/Animations」フォルダに作成されたAnimatorはひとつを残して削除します。

タワーディフェンス46

条件に合わせて移動アニメーションを切り替える

Blend Treeという機能を使って、移動アニメーションを切り替えます。Blend Treeとは複数のアニメーションを滑らかに切り替えるための仕組みです。

STEP

ヒエラルキーの「Enemy」オブジェクトを選択した状態で、メニューバーの「Window > Animation > Animator」を選択します。

タワーディフェンス47

「Animator」ウインドウが開くので、どこか適当なところにドラッグしてタブ化しましょう。

STEP

Animatorビューの「Parameters」タブで「+」をクリックし「Float」を選択します。浮動小数点数の値を持つパラメーターが追加されるので名前を「X」にします。

タワーディフェンス48

もう一度同じ手順で「Float」を選択し、名前が「Y」のパラメーターを追加します。

タワーディフェンス49
STEP

Animatorビューの何もないところでで右クリック「Create State > From New Blend Tree」を選択します。

タワーディフェンス50

「Blend Tree」という名前のステートが作成されるので、インスペクターで名前を「Walk」に変更します。

タワーディフェンス51
STEP

Animatorビューの「Entry」ステートの上で右クリック「Set StateMachine Default State」を選択して、矢印を「Walk」につなげます。

タワーディフェンス52
タワーディフェンス53

「Enemy0_right」ステートは削除しちゃってOKです。

Entryはアニメーションのフローのスタートポイントです。Walkに矢印をつなげてデフォルトステートに設定したのでゲーム開始時に無条件にWalkステートが実行されます。

STEP

「Walk」ステートをダブルクリックするとBlend Treeの設定画面に切り替わります。

タワーディフェンス54
STEP

「Brend Tree」ステートをクリックするとインスペクターの表示が切り替わるので、「Blend Type」「2D Simple Directional」に変更します。

「Parameters」の右側を「Y」に変更します。

タワーディフェンス55

Animatorビューの「Blend Tree」ステートにもXとYのパラメーターが表示されました。

タワーディフェンス56
STEP

インスペクターの「Motion」にアニメーションを登録して再生するための条件を設定します。

「Motion」「+」をクリックして「Add Motion Field」を選択します。

タワーディフェンス57

まずは右方向へ移動するときのアニメーションを登録します。「None (Motion)」をクリックして「Enemy0_right」を選択します。「Pos X」1「Pos Y」0に設定します。

タワーディフェンス58

同じ手順で、左、上、下方向へ移動するときのアニメーションも設定します。

タワーディフェンス59
MotionPos XPos Y
Enemy0_right10
Enemy0_left-10
Enemy0_up01
Enemy0_down0-1

Animatorビューはこんな感じになりました。

タワーディフェンス60
STEP

動作確認をします。

インスペクターの下の方にある「Blend Tree」の再生ボタンを押します。「Parameters」の赤いポッチをドラッグするとアニメーションが切り替わります。

スクリプトでアニメーションを切り替える

EnemyControllerスクリプトを修正して、敵の移動方向を取得しアニメを切り替えます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening; // DOTweenを使うために必要な宣言
using System.Linq; // Linqを使うために必要な宣言

public class EnemyController : MonoBehaviour
{
    [SerializeField, Header("移動経路の情報")]
    private PathData pathData;
    [SerializeField, Header("移動速度")]
    private float speed;
    private Vector3[] path; // pathDataから取得した座標を格納するための配列
    private Animator animator; // Animatorコンポーネントの取得

    void Start()
    {
        // Animatorコンポーネントを取得して代入
        TryGetComponent(out animator);

        // 経路を取得
        path = pathData.pathArray.Select(x => x.position).ToArray();
        // 経路の総距離を計算
        float totalDistance = CalculatePathLength(path);
        // 移動時間を計算 (距離 ÷ 速度)
        float moveDuration = totalDistance / speed;
        // 経路に沿って移動
        // transform.DOPath(path, moveDuration).SetEase(Ease.Linear); (以下に修正)
        transform.DOPath(path, moveDuration)
                 .SetEase(Ease.Linear)
                 .OnWaypointChange(x => ChangeWalkingAnimation(x));
    }

    /// <summary>
    /// 経路の総距離を計算
    /// </summary>
    /// <param name="path">経路座標の配列</param>
    /// <returns>経路の総距離</returns>
    private float CalculatePathLength(Vector3[] path)
    {
        float length = 0f;
        for (int i = 0; i < path.Length - 1; i++)
        {
            // 各セグメントの距離を計算して合計
            length += Vector3.Distance(path[i], path[i + 1]);
        }
        return length;
    }

    /// <summary>
    /// 敵の進行方向を取得してアニメを変更
    /// </summary>
    private void ChangeWalkingAnimation(int index)
    {
        // 次の移動先がない場合は処理を終了
        if (index >= path.Length)
        {
            return;
        }
        // 左方向
        if (transform.position.x > path[index].x)
        {
            animator.SetFloat("Y", 0f);
            animator.SetFloat("X", -1.0f);
        }
        // 上方向
        else if (transform.position.y < path[index].y)
        {
            animator.SetFloat("X", 0f);
            animator.SetFloat("Y", 1.0f);
        }
        // 下方向
        else if (transform.position.y > path[index].y)
        {
            animator.SetFloat("X", 0f);
            animator.SetFloat("Y", -1.0f);
        }
        // 右方向
        else
        {
            animator.SetFloat("Y", 0f);
            animator.SetFloat("X", 1.0f);
        }
    }
}

31行目、DOTweenのOnWaypointChange()メソッドを追加しました。このメソッドは経路として指定した座標に到達するたびに呼び出されます。つまり、経路の曲がり角に到達するたびにChangeWalkingAnimation()関数が実行されます。引数には移動経路のインデックスが渡されます。

ChangeWalkingAnimation()関数は、敵の移動方向に応じてアニメーターのXYに値をセットします。

動作確認しましょう。

移動方向に応じてスライムの向きが変わりました。いえい。

コードのリファクタリング

ChangeWalkingAnimation()関数がなんだか冗長だなぁと思いませんか。私は思います。

というわけで、ChatGPT氏にリファクタリングをお願いしました。

/// <summary>
/// 敵の進行方向を取得してアニメを変更
/// </summary>
private void ChangeWalkingAnimation(int index)
{
    // 次の移動先がない場合は処理を終了
    if (index >= path.Length)
    {
        return;
    }

    // 移動先の方向を計算
    Vector2 direction = (path[index] - transform.position).normalized;

    // XとY方向をアニメーターに設定
    animator.SetFloat("X", Mathf.Round(direction.x));
    animator.SetFloat("Y", Mathf.Round(direction.y));
}

はい、めっちゃシンプルになりましたね。自力で書けと言われても絶対に書けないコードです。引き算で移動方向を計算できるんですね。なぜ?

オブジェクトをプレハブ化する

ゲーム内に敵は何体も出現します。なのでEnemyオブジェクトをプレハブ化して使い回します。

ヒエラルキーの「Enemy」オブジェクトをプロジェクトの「Assets/Prefabs」フォルダにドラッグ&ドロップして、プレハブ化します。するとEnemyの「Enemy Controller > Path Data」変数のアサインが外れてしまいました。これはプレハブ化したオブジェクトはヒエラルキーのオブジェクトを参照できないためです。

この問題を解決するために、「Path」オブジェクトもプレハブ化します。そして、プレハブの「Enemy」にプレハブの「Path」をアサインして一件落着です。

さいごに

今回は敵の移動方向に応じてアニメーションを変更する処理を実装しました。

このペースでやってたら、いつゲームが完成するのだろうとちょっと不安になっております。

でわでわ

タワーディフェンスを作る(5)

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次