1. はじめに
こんにちは!今回も Unityで2Dタワーディフェンスゲーム を作っていきましょう。
この記事では、敵の移動ルートを設定し、実際に敵が移動する処理 を作成していきます。また、敵が攻撃を受けたときにアニメーションを切り替える処理 も実装し、よりリアルな動きに仕上げていきます。
また、マップの作成方法 についても解説し、ゲームの見た目を整えていきます。
これで、敵が決まったルートを移動しながら、攻撃を受けると反応するようになります!
「Unityでタワーディフェンスゲームを一から作りたい方へ!」
この記事では、タワーディフェンスゲームの 敵の移動、アニメーション、マップ作成 をゼロから解説します。ただし、すぐに本格的なタワーディフェンスゲームを作りたい方には、「Tower Defense Starter Kit」がおすすめ!
このアセットを使えば、タワー配置、敵のウェーブ管理、攻撃システムなどがすぐに実装できます。詳しくはこちら👇
👉 Tower Defense Starter Kit
👉 Tower Defense Toolkit 4 (TDTK-4)
この記事で学べること
- 敵の移動ルートの作成方法
- エディタ拡張を使って移動ポイントを直感的に配置する方法
- 敵の移動処理の実装
- 敵が攻撃を受けたときにアニメーションを切り替える方法
- マップを作成し、敵が移動する環境を整える方法
必要な準備(前回の記事の復習)
このチュートリアルは、2Dタワーディフェンスゲームの作り方パート2 の続きです。
前回までに以下の実装を行いました。
✅ 敵の配置とアニメーション
- 敵キャラを作成し、歩行アニメーションやダメージアニメーションを設定しました。
✅ 武器の設置と弾の発射
- 武器が範囲内の敵を検知し、弾を発射する処理を実装しました。
- 弾が敵を追尾し、ヒット時にダメージを与えるようにしました。
✅ 弾のリロードと発射間隔の調整
- 弾のリロード処理を実装し、一定間隔で弾を発射できるようにしました。
これらの処理が正しく動作していれば、次のステップとして 敵の移動ルートの作成 に進むことができます。

💡 もし前回の記事の内容がまだ完成していない場合は、先にそちらをチェックしてみてください!
準備ができたら、早速 敵の移動ルートの作成 から始めていきましょう!
2. 敵の移動ポイントの作成
タワーディフェンスゲームでは、敵が特定のルートを通って移動する必要があります。
今回は、移動ポイントを設定し、敵がそれに沿って移動する仕組みを作成 していきます。
まずは、敵が通る移動ポイント(Waypoints) を管理するスクリプトを作成し、エディタ上で視覚的に確認できるようにしていきましょう!
1. 移動ポイントの管理スクリプトを作成
敵の移動ルートを設定するために、新しく MovePointスクリプト を作成します。
📌 手順
- Systemフォルダ を作成
- 「Project」ウィンドウで Assetsフォルダ 内に Systemフォルダ を作成します。
- MovePointスクリプトを作成
- Systemフォルダ内で右クリック →「Create」→「C# Script」を選択
- スクリプト名を「MovePoint」に変更 します。
- MovePointオブジェクトを作成
- 「Hierarchy」ウィンドウで右クリック → 「Create Empty」を選択し、オブジェクト名を MovePoint に変更します。
- MovePointスクリプトをアタッチ
- 作成した MovePointスクリプト を MovePointオブジェクトにドラッグ&ドロップ してアタッチします。
2. 移動ポイントの配列を作成
MovePointスクリプトを開き、以下のコードを入力してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movepoint : MonoBehaviour
{
//移動ポイントの配列
public Vector3[] points;
}
💡 解説
public Vector3[] points;
- Vector3型の配列 を用意し、移動ポイントを格納します。
- エディタ上で好きな数だけ移動ポイントを追加できるようになります。
スクリプトを保存したら、Unityのエディタに戻り、MovePointオブジェクトのInspectorを確認 しましょう。
「Points」という項目が追加されているので、そこに 4つの移動ポイントを設定 していきます。
3. 移動ポイントをエディタで確認
現在の状態では、設定したポイントがどこにあるのか エディタ上では見えない ので、
視覚的に確認できるように ギズモ(Gizmos) を使って移動ポイントを表示するコードを追加します。
📌 手順
- MovePointスクリプトを開く
- 以下のコードを追加する
//エディタ上で見えるようにする
private void OnDrawGizmos()
{
//for文で配列の数値分処理する
for (int i = 0; i < points.Length; i++)
{
//色を指定
Gizmos.color = Color.yellow;
//ポジション、半径
Gizmos.DrawWireSphere(points[i], 0.5f);
}
}
/// <summary>
/// 引数で渡された数値と同じポイントの位置を返す
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Vector3 GetMovePointPosition(int index)
{
//敵の移動に必要
return points[index];
}
💡 解説
OnDrawGizmos()
- Gizmos を使って、移動ポイントを視覚的に表示します。
DrawWireSphere(points[i], 0.5f);
を使い、各ポイントの位置に半径0.5のワイヤースフィアを描画します。Gizmos.color = Color.yellow;
でポイントの色を黄色に設定。
GetMovePointPosition(int index)
- 指定した index の移動ポイントの位置を返すメソッド。
- 敵が次に向かう移動ポイントの座標 を取得するのに使用します。
4. エディタで確認
ここまでの作業が終わったら、Unityエディタに戻って確認 してみましょう。
- MovePointオブジェクトを選択
- Inspectorウィンドウの「Points」に4つのポイントを追加
- 「Size」を 4 に設定し、適当な座標を入力
- 例:yamlコピーする編集する
Point 0: (-3, 0, 0) Point 1: (0, 1, 0) Point 2: (3, 1, 0) Point 3: (6, 0, 0)
- 例:yamlコピーする編集する
- 「Size」を 4 に設定し、適当な座標を入力
- Sceneビューで移動ポイントが黄色い円で表示されているか確認

もし円が表示されていない場合は、SceneビューのGizmosボタン をクリックして、Gizmosが有効になっているかチェックしてください。

これで、敵が移動するためのポイントを作成 し、エディタ上で視覚的に確認できるようになりました!次は、敵がこの移動ポイントを順番に移動する処理を実装 していきましょう!
3. エディタ拡張で移動ポイントを操作しやすくする
前のステップでは、敵の移動ルートを設定するための移動ポイント(MovePoint)を作成 しました。
しかし、現在のままだと 移動ポイントの位置をInspectorで数値入力する必要があり、調整が面倒 です。
そこで、エディタ拡張を活用して、移動ポイントを直感的に配置できるようにカスタマイズ していきます!
1. エディタ拡張の概要
Unityでは、Editor拡張 を使うことで、カスタムのインスペクターやシーンビューの編集ツールを作成 できます。
今回は、シーンビュー上で移動ポイントをマウスで自由に動かせるように し、さらに 番号表示やCTRL+Zでの復元機能 も追加します。
2. MovePointEditorスクリプトの作成
まず、エディタ拡張用のスクリプトを作成しましょう。
📌 手順
- Editorフォルダを作成
- 「Project」ウィンドウのAssetsフォルダ内に「Editor」フォルダを作成 します。
- ※ Editorフォルダは必ずこの名前にしてください! Unityがエディタ専用スクリプトとして認識するためです。
- MovePointEditorスクリプトを作成
- Editorフォルダ内で右クリック →「Create」→「C# Script」を選択
- スクリプト名を「MovePointEditor」に変更 します。
- MovePointEditorスクリプトを開き、以下のコードを入力
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Movepoint))]
public class MovePointEditer : Editor
{
//変数に格納する
Movepoint movepoint => target as Movepoint;
private void OnSceneGUI()
{
//色を指定
Handles.color = Color.yellow;
for (int i = 0; i < movepoint.points.Length; i++)
{
//EndChangeCheckとの間でシーン内での変化がないのか確認する
EditorGUI.BeginChangeCheck();
//ポイントの位置を取得
Vector3 currentWaypoint= movepoint.points[i];
//ハンドルを生成して変数に格納する
Vector3 newWaypoint = Handles.FreeMoveHandle
(currentWaypoint, Quaternion.identity, 0.7f, new Vector3(0.3f, 0.3f, 0.3f), Handles.SphereHandleCap);
//ハンドル番号の生成
GUIStyle textStyle= new GUIStyle();
textStyle.fontSize= 18;
textStyle.normal.textColor = Color.white;
Vector3 textPos = Vector3.down * 0.35f + Vector3.right * 0.35f;
//ラベルの発生位置、表示内容、GUIの設定
Handles.Label(movepoint.points[i] + textPos, $"{i + 1}", textStyle);
EditorGUI.EndChangeCheck();
if (EditorGUI.EndChangeCheck())
{
//位置の保存CTRL+Zで戻せるようにする
Undo.RecordObject(target, "Move");
//動かしたハンドル位置に変更する
movepoint.points[i] = newWaypoint;
}
}
}
}
3. エディタ拡張の機能解説
このスクリプトを適用することで、移動ポイントの編集がシーンビュー上で簡単に行えるようになります!
✅ マウスでポイントをドラッグして移動できる
✅ 移動ポイントの番号がシーンビューに表示される
✅ CTRL+Zで位置を元に戻せる
4. エディタで確認
スクリプトを保存したら、Unityエディタに戻って動作を確認 しましょう。
📌 確認手順
- MovePointオブジェクトを選択
- シーンビューで移動ポイントが黄色い丸(ハンドル)になっているか確認
- ハンドルをドラッグしてポイントを移動できるか確認
- ポイントの番号が表示されているか確認
- CTRL+Zを押して、ポイントの移動が元に戻るか確認

5. うまく動作しない場合のチェックポイント
✅ Editorフォルダの名前が間違っていないか
✅ MovePointEditorスクリプトが正しくMovePointクラスを参照しているか
✅ シーンビューの「Gizmos」が有効になっているか(画面上部のGizmosボタンを確認)

これで、敵の移動ルートの編集が直感的に行えるようになりました!
次は、敵がこの移動ポイントを順番に移動する処理を実装 していきましょう!
4. 敵の移動処理の作成
前のステップで、敵が移動するためのルート(移動ポイント)を設定 しました。
次は、実際に敵が移動ポイントを順番に進んでいく処理を実装 していきます。
敵が 最初の移動ポイントに向かい、目的地に到達したら次のポイントへ移動 するようにプログラムを組んでいきましょう!
1. 敵の移動ロジックを追加
まず、Enemyスクリプト に移動処理を追加します。
📌 手順
- Enemyスクリプトを開く
- 以下のコードを追加
using System;
//インスペクターに表示する必要が無くなったのでNonSerializedにしておく
[NonSerialized]public EnemyHP enemyHP;
//移動速度設定用
[SerializeField] private float setMoveSpeed = 3f;
//移動速度
private float moveSpeed;
[NonSerialized] public Movepoint movepoint;
//向かうポイントの番号
private int currentMovepointIndex;
//CurrentPointPositionが行われるたびに後半の処理が行われる
public Vector3 CurrentPointPosition => movepoint.GetMovePointPosition(currentMovepointIndex);
void Start()
{
//向かうポイントを設定
currentMovepointIndex= 0;
//移動速度の設定
SetMoveSpeed();
//指定のコンポーネントがついているオブジェクトを探して格納する
movepoint = FindObjectOfType<Movepoint>().GetComponent<Movepoint>();
}
private void SetMoveSpeed()
{
moveSpeed = setMoveSpeed;
}
void Update()
{
Move();
}
private void Move()
{
//ポジションを移動
transform.position = Vector3.MoveTowards(transform.position,CurrentPointPosition,moveSpeed * Time.deltaTime);
}
2. 目的地を更新しながら移動する処理
次に、敵が目的地に到達したら次のポイントへ移動する処理 を追加します。
📌 手順
- EnemyスクリプトのUpdateメソッドを修正
- 以下のコードを追加
void Update()
{
//現在の目的のポイントに到達しているかの判定
if (NextPointReached())
{
//次の目的ポイントに更新する
UpdatePointIndex();
}
}
private void UpdatePointIndex()
{
//最終地点でなければ目標ポイントを更新する
if (currentMovepointIndex < movepoint.points.Length - 1)
{
currentMovepointIndex++;
}
}
private bool NextPointReached()
{
//次のポイントまでの残りの距離を変数に格納
float distance = (transform.position - CurrentPointPosition).magnitude;
//判定
if (distance < 0.1)
{
return true;
}
return false;
}
3. SortingLayerを変更
現在の状態では、敵が他のオブジェクトと重なった際に表示順が適切でない可能性があります。
敵がマップや他のオブジェクトと適切な表示順になるよう、SortingLayerを変更 します。
📌 手順
- Enemyオブジェクトを選択
- Inspectorウィンドウを開く
- 「SpriteRenderer」コンポーネントの「Sorting Layer」を「Enemy」に変更
💡 SortingLayerが設定されていない場合
- 「Add Sorting Layer」をクリック
- 「Enemy」というレイヤーを作成
- Enemyオブジェクトの「Sorting Layer」を「Enemy」に設定
4. Unityエディタで確認
ここまでの設定が完了したら、実際に 敵が移動ポイントを順番に移動するか確認 しましょう。
📌 確認手順
- Unityを再生
- 敵が最初の移動ポイントに向かって動くか確認
- 目的地に到達したら次のポイントへ移動するか確認
- 最後の移動ポイントまで順番に移動するかチェック
💡 動作しない場合のチェックポイント ✅ MovePointオブジェクトがシーン内にあるか
✅ EnemyのInspectorにある「Movepoint」に正しくオブジェクトがアタッチされているか
✅ 移動ポイントが適切に設定されているか(エディタ上で確認)

これで、敵が移動ルートを順番に進む処理 を作成できました!
次は、敵が攻撃を受けた際にアニメーションを切り替える処理 を実装していきましょう!
5. 敵の被弾アニメーションの実装
タワーディフェンスゲームでは、敵が攻撃を受けたときにダメージを受けたことがわかるようなアニメーション を再生することで、ゲームの視覚的なフィードバックを向上させます。
今回は、敵がダメージを受けた際に
✅ 移動を一時的に停止 し
✅ 被弾アニメーションを再生 し
✅ 一定時間後に移動を再開 する
という流れで、アニメーションの処理を実装していきます!
1. EnemyAnimationsスクリプトの作成
まず、敵のアニメーションを制御する EnemyAnimationsスクリプト を作成し、Enemyオブジェクトにアタッチ します。
📌 手順
- Enemyフォルダ内で新しいC#スクリプトを作成
- スクリプト名を「EnemyAnimations」にする
- 作成したスクリプトをEnemyオブジェクトにアタッチ
- 以下のコードを追加
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAnimations : MonoBehaviour
{
private Animator animator;
private Enemy enemy;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
enemy = GetComponent<Enemy>();
}
// Update is called once per frame
void Update()
{
}
private void PlayHitAnimation()
{
animator.SetTrigger("hit");
}
/// <summary>
/// 移動を止めてアニメーションを再生
/// </summary>
/// <param name="enemy"></param>
private void EnemyHit(Enemy enemy)
{
if (this.enemy == enemy)
{
StartCoroutine(PlayHurt());
}
}
private IEnumerator PlayHurt()
{
//移動スピードを0にする
enemy.StopMovement();
//アニメーションの再生
PlayHitAnimation();
//再生待機中
yield return new WaitForSeconds(StopTime());
//移動再開
enemy.SetMoveSpeed();
}
private float StopTime()
{
//アニメーションの長さ+調整数値を返す
return animator.GetCurrentAnimatorStateInfo(0).length + 0.3f;
}
//イベントに関数を登録&解除
private void OnEnable()
{
EnemyHP.OnEnemyHit += EnemyHit;
}
private void OnDisable()
{
EnemyHP.OnEnemyHit -= EnemyHit;
}
}
//関数がprivateになっていてエラーになっているものはpublicにする
2. EnemyHPスクリプトに被弾イベントを追加
次に、敵がダメージを受けたことを通知する仕組み を追加します。
📌 手順
- EnemyHPスクリプトを開く
- 以下のコードを追加
// 被弾イベント
public static Action<Enemy> OnEnemyHit;
// Enemyを格納
private Enemy enemy;
// Start関数内でコンポーネントを取得
void Start()
{
enemy = GetComponent<Enemy>();
}
// ReduceHPメソッド内(DeathCheckの前)に追加
// 被弾アニメーションを実行
OnEnemyHit?.Invoke(enemy);
💡 解説
OnEnemyHit
イベントを追加し、敵がダメージを受けたことを通知 できるようにしました。ReduceHP
メソッドのDeathCheck
の前にOnEnemyHit?.Invoke(enemy);
を追加し、
ダメージを受けたタイミングで被弾アニメーションを再生 できるようにしました。
3. Enemyスクリプトにアニメーション再生時の移動停止処理を追加
次に、アニメーションが再生されている間は、敵の移動を一時停止する処理を追加します。
📌 手順
- Enemyスクリプトを開く
- 以下のコードを追加
/// <summary>
/// 敵の移動を停止
/// </summary>
public void StopMovement()
{
moveSpeed = 0f;
}
/// <summary>
/// 敵の移動を再開
/// </summary>
public void SetMoveSpeed()
{
moveSpeed = setMoveSpeed;
}
💡 解説
StopMovement()
- 移動速度を0にして、敵が止まるようにする。
SetMoveSpeed()
- アニメーションが終わった後、元の移動速度に戻す。
これにより、攻撃を受けた敵がアニメーション中は動かず、終了後に再び動くように なります。
4. Unityエディタで確認
ここまでの設定が完了したら、実際に 敵が攻撃を受けたときにアニメーションが再生され、移動が止まるか確認 しましょう。
📌 確認手順
- Unityを再生
- 敵が武器の攻撃を受けたときに、移動が一時停止するか確認
- 被弾アニメーションが再生されるか確認
- アニメーションが終わったら移動が再開するか確認
💡 動作しない場合のチェックポイント ✅ Enemyオブジェクトに「Animatorコンポーネント」が正しく設定されているか
✅ アニメーションの「hit」トリガーが正しく設定されているか
✅ EnemyHPスクリプトの「OnEnemyHit」イベントが登録されているか
6. 敵のHPが0になったときのアニメーション
敵が攻撃を受けてHPが0になったとき、即座に消えてしまうのではなく、倒れるアニメーションを再生してから消滅する処理 を実装していきます。
これにより、敵が倒れたことがプレイヤーに伝わりやすくなり、ゲーム全体の演出が向上 します。
1. HPが0になったときに即座に消えないようにする
現在の EnemyHPスクリプト では、敵のHPが0になると gameObject.SetActive(false);
によって即座に非表示になっています。
これを修正し、倒れるアニメーションが終わってから消滅するように変更 します。
📌 手順
- EnemyHPスクリプトを開く
- 以下のコードを修正・追加
//animationsを扱うための変数
private EnemyAnimations enemyAnimations;
//スタート関連に書く
enemyAnimations= GetComponent<EnemyAnimations>();
//DeathCheckのif文の中に書く
//非表示にするは消す
//StopTimeがprivateだったらpublicにする
//被弾アニメーションを再生してから消滅させる
Invoke("Die", enemyAnimations.StopTime());
private void Die()
{
ResetHealth();
}
private void ResetHealth()
{
currentHp = hp;
hpBarImage.fillAmount = 1f;
gameObject.SetActive(false);
}
💡 解説
enemyAnimations = GetComponent<EnemyAnimations>();
- EnemyAnimationsスクリプトの参照を取得
DeathCheck()
でHPが0になったとき、すぐには非表示にしないInvoke("Die", enemyAnimations.StopTime());
を呼び出し、倒れるアニメーションが終わってから非表示 にする。
Die()
メソッドを作成し、HPをリセットgameObject.SetActive(false);
で敵を消すが、その前にHPをリセットし、再利用できるようにする。
7. マップの作成
タワーディフェンスゲームでは、敵が通る道を設定し、マップ全体のバランスを整えることが重要 です。
このステップでは、マップを作成し、敵の移動ルートを決定 していきます。
また、MovePoint(移動ポイント)の開始位置を画面外に配置 し、自然な形で敵が出現するように調整 します。
1. マップの素材を用意
まずは、マップ用の背景や道の素材を準備します。
以下の方法でマップ素材を用意しましょう。
📌 手順
- 無料のマップ素材をダウンロード
- Unity Asset Store や フリー素材サイト(ぴぽや、OpenGameArt など)からマップ用の画像をダウンロード
- 道、草原、壁などの画像を準備
- Unityの「Sprites」フォルダにインポート
- ダウンロードした画像を**「Sprites」フォルダ** に入れる
- Texture Typeを「Sprite」に変更
- 素材を選択し、「Inspector」ウィンドウで「Texture Type」を「Sprite」に設定
- 「Apply」を押して変更を適用
2. MovePointの開始位置を画面外に配置
敵が 突然画面内に現れると違和感があるため、移動開始地点を画面外に配置 しましょう。
📌 手順
- MovePointオブジェクトを選択
- Inspectorウィンドウで「Points」の最初の値を変更
Point 0
の X座標を画面外に設定(例:(-5, 0, 0)
など)
- 敵のスポーン位置を調整
- 敵が画面外からスムーズに登場するよう、適切な位置に配置する
4. 全体的なバランス調整
最後に、マップ全体のバランスを確認し、調整 します。

📌 調整ポイント
✅ 敵の移動ルートが明確か確認
✅ マップの背景・道の配置が自然かチェック
✅ MovePointの位置を微調整して、スムーズに移動するか確認
✅ 敵が画面外から登場し、自然に進んでいくかテスト
5. Unityエディタで確認
- Unityを再生
- 敵が正しいルートを通るか確認
- 道と敵の動きがマッチしているか確認
- 必要に応じてMovePointの位置を微調整
💡 動作しない場合のチェックポイント ✅ マップのSorting Layerが正しく設定されているか
✅ MovePointの位置が適切に設定されているか
✅ 敵の移動処理が正しく動いているか(前回のコードが正しく実装されているか)

これで、敵が自然に登場し、移動ルートに沿って進むマップが完成 しました!
次回は、敵の出現を管理する「ウェーブシステム」を作成し、ゲームをより本格的にしていきます!
8. まとめ
お疲れさまでした!この記事では、2Dタワーディフェンスゲーム の開発をさらに進め、敵の移動ルートやアニメーション、マップの作成 について学びました。
これで、敵が決まったルートを移動し、攻撃を受けるとアニメーションを再生しながらHPが減少し、HPが0になると倒れる演出ができるようになりましたね!
📌 この記事で学んだこと
✅ 敵の移動ポイント(MovePoint)の作成
→ 敵がルートに沿って移動するためのポイントを設定
✅ エディタ拡張で移動ポイントを視覚的に調整
→ マウスでドラッグして移動しやすくし、ポイントの番号を表示
✅ 敵の移動処理の実装
→ MovePointのデータをもとに、敵が順番にポイントを移動
✅ 敵が攻撃を受けたときのアニメーション
→ ダメージを受けると一時停止し、アニメーションを再生
✅ 敵がHP0になったときの倒れるアニメーションの実装
→ HPが0になっても即座に消えず、倒れるアニメーションを再生後に消滅
✅ マップの作成と移動ルートの決定
→ マップの背景や道を配置し、敵が自然に登場するよう調整
次回予告:ウェーブシステムと敵の出現管理
ここまでで、敵の基本的な動作が完成 しました!
次回は、「ウェーブシステム」と「敵の出現管理」 に取り組みます。
🔹 ウェーブシステムとは?
→ 一定間隔で敵が出現し、徐々に難易度が上がる仕組み
🔹 実装予定の内容
✅ 敵のスポーン管理(一定時間ごとに敵を出現)
✅ ウェーブの設定(ステージごとに出現する敵の数や間隔を調整)

次の記事では、このウェーブシステムを作成し、よりゲームらしい進行ができるようにしていきます!お楽しみに!🚀
よくある質問(FAQ)
- Q敵の移動がうまくいかない
- A
MovePointオブジェクトがシーン内に存在するか 確認してください。また、Enemyスクリプトで正しく MovePointの位置を参照しているか も確認しましょう。
- Q移動ポイントがエディタで表示されない
- A
MovePointEditorスクリプトが正しく機能しているか 確認してください。スクリプトがEditorフォルダ内にあり、[CustomEditor(typeof(Movepoint))] の指定があるかをチェックしましょう。
- Q敵のアニメーションが再生されない
- A
Animatorが正しく設定されているか 確認してください。また、EnemyAnimationsスクリプトが OnEnable() でイベント登録 を行っているか確認しましょう。