1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

タワーデフェンスゲーム Unity 敵の機能 5/10 Object Poolを作って複数の敵オブジェクトを出現する様に実装

Last updated at Posted at 2023-04-23

概要

前回の続きです。

今回は、複数敵が出現するように実装します。
ObjectPoolerを使います。

以下GIF画像は、再生時に敵が複数生成されている様子です。
111111.gif

2Wave以降 最終地点に直行してますが次回改善します。
次へ

開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

UnityEditorの画像

Enemyプレハブの設定

image.png

Spawnerオブジェクト

image.png

実装のポイント

Enemyクラス上でWaypointをSpawnerクラスから参照できるようにします。
理由としては、Enemyクラスがアタッチされているオブジェクトをプレファブ化するとWaypointに参照できなくなるからです。

対処方法としてはSpawnerクラスで、Enemyのプレファブを生成する際にWaypointクラスを渡すようにします。

image.png

コード部分

Enemy.cs
using System;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public static Action OnEndReached;
    
    [SerializeField] private float moveSpeed = 3f;
-    [SerializeField] private Waypoint waypoint;
+    public Waypoint Waypoint { get; set; }


-    public Vector3 CurrentPointPosition => waypoint.GetWaypointPosition(_currentWaypointIndex);
+    public Vector3 CurrentPointPosition => Waypoint.GetWaypointPosition(_currentWaypointIndex);

    private int _currentWaypointIndex;
    
    private void Start()
    {
        _currentWaypointIndex = 0;
    }

    private void Update()
    {
        Move();
        if (CurrentPointPositionReached())
        {
            UpdateCurrentPointIndex();
        }
    }

    private void Move()
    {
-        Vector3 currentPosition = waypoint.GetWaypointPosition(_currentWaypointIndex);
+        Vector3 currentPosition = Waypoint.GetWaypointPosition(_currentWaypointIndex);
        transform.position = Vector3.MoveTowards(transform.position, currentPosition, moveSpeed * Time.deltaTime);
    }
    
    private bool CurrentPointPositionReached()
    {
        return Vector3.Distance(transform.position, CurrentPointPosition) < 0.1f;
    }

    private void UpdateCurrentPointIndex()
    {
-         int lastWaypointIndex = waypoint.Points.Length - 1;
+        int lastWaypointIndex = Waypoint.Points.Length - 1;
        if (_currentWaypointIndex < lastWaypointIndex)
        {
            _currentWaypointIndex++;
        }
        else
        {
            ReturnEnemyToPool();
            
        }
    }

    
    private void ReturnEnemyToPool()
    { 
        OnEndReached?.Invoke();
        ObjectPooler.ReturnToPool(gameObject);
    }
}

Spawner.cs
using System;
+ using System.Collections;
using UnityEngine;


    public class Spawner : MonoBehaviour
    {
        [SerializeField]  private  int enemyCount = 10;
        // Btw = Between
        [SerializeField] private float delayBtwSpawns;
+        [SerializeField] private float delayBtwWaves = 1f;

+        private int _enemiesRemaining;
        
        private int _enemiesSpawned;
        private float _spawnTimer;
        private ObjectPooler _objectPooler;
+        private Waypoint _waypoint;

        private void Start()
        {
            _objectPooler = GetComponent<ObjectPooler>();
+            _waypoint = GetComponent<Waypoint>();
            
+            _enemiesRemaining = enemyCount;
        }

        private void Update()
        {
            _spawnTimer -= Time.deltaTime;
            if (_spawnTimer < 0)
            {
                _spawnTimer = delayBtwSpawns;
                if (_enemiesSpawned < enemyCount)
                {
                    SpawnEnemy();
                    _enemiesSpawned++;
                }
            }
        }
        
        // ReSharper disable Unity.PerformanceAnalysis
        private void SpawnEnemy()
        {
            GameObject newInstance = _objectPooler.GetInstanceFromPool();
+            Enemy enemy = newInstance.GetComponent<Enemy>();
+            enemy.Waypoint = _waypoint;
+            enemy.transform.localPosition = transform.position;
            newInstance.SetActive(true);
        }

        private IEnumerator NextWave()
        {
            yield return new WaitForSeconds(delayBtwWaves);
            _enemiesRemaining = enemyCount;
            _spawnTimer = 0f;
            _enemiesSpawned = 0;
        }
        
        private void RecordEnemyEndReached()
        {
            _enemiesRemaining--;
            if (_enemiesRemaining <= 0)
            {
                StartCoroutine(NextWave());
            }
        }
        private void OnEnable()
        {
            Enemy.OnEndReached += RecordEnemyEndReached;
        }
        
        private void OnDisable()
        {
            Enemy.OnEndReached -= RecordEnemyEndReached;
        }
    }


参考

Section4 15

github コミット分

章まとめ

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?