タワーデフェンスゲーム　Unity タレット機能8/10　26 一定間隔毎に弾が出てEnemyにダメージを与える

# 概要

目次

https://qiita.com/RYA234/items/c9925ce07d6afe64be7e

今回は敵がタレットの射程内にある場合、弾を発射するようにします。
今まではGボタンをおして弾を発射していましが　自動で弾を発射できるようにします。
以下gifアニメはその時の様子です。
![autoatack.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/56e334af-bd6b-c6c0-672b-cbd06865063f.gif)

# 開発環境

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

# UnityEditor上の設定

変更点は無し

# 実装のポイント
Projectileクラス　
狙う敵を初期化するメソッドResetProjectileを追加します。
ResetProjectileは敵が弾被弾後実行されます。



TurretProjectileクラス  
Updateメソッド内に一定時間置きに射撃する処理を追加します。

新規メソッドにIsTurretEmptyとResetTurretProjectileを追加します。
IsTurretEmptyは同クラス内のUpdateメソッド内で実行され、範囲内に敵がいる時に実行します。

ResetTurretProjectileは、弾を初期化するメソッドでProjectileクラスのMoveProjectilで実行されます。

# コード部分
```diff_c_sharp:TurretProjectile.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurretProjectTile : MonoBehaviour
{

    [SerializeField] private Transform projecttileSpawnPosition;
    private ObjectPooler _pooler;
    private Turrets _turret;
    private Projectile _currentProjectileLoaded;
+    [SerializeField] private float delayBtwAttacks = 0.3f;

+    private float _nextAttackTime;
    
    private void Start()
    {
        _pooler = GetComponent<ObjectPooler>();
        _turret = GetComponent<Turrets>();

+        LoadProjecttile();
        
    }

    private void Update()
    {
-        if (Input.GetKeyDown(KeyCode.G))
+        if (IsTurrentEmpty())
        {
            LoadProjecttile();
        }
        
+        if(Time.time > _nextAttackTime)
+        {
            if (_turret.CurrentEnemyTarget != null && _currentProjectileLoaded != null &&
                _turret.CurrentEnemyTarget.EnemyHealth.CurrentHealth > 0f)
            {
                _currentProjectileLoaded.transform.parent = null;
                _currentProjectileLoaded.SetEnemy((_turret.CurrentEnemyTarget));
            }

+            _nextAttackTime = Time.time + delayBtwAttacks;
+        }

        
    }

    private void LoadProjecttile()
    {
        GameObject newInstance = _pooler.GetInstanceFromPool();
        newInstance.transform.position = projecttileSpawnPosition.position;
        newInstance.transform.SetParent(projecttileSpawnPosition);

        _currentProjectileLoaded = newInstance.GetComponent<Projectile>();
+        _currentProjectileLoaded.TurretOwner = this;
+        _currentProjectileLoaded.ResetProjectile();
        
        newInstance.SetActive(true);
        

    }

+    private bool IsTurrentEmpty()
+    {
+        return _currentProjectileLoaded == null;
+    }
+    public void ResetTurretProjectile()
+    {
+        _currentProjectileLoaded = null;
+    }


}




```

```diff_c_sharp:Projectile.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Projectile : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 10f;
    private Enemy _enemyTarget;
    [SerializeField] private float damage = 2f;
    [SerializeField] private float minDistanceToDealDamage = 0.1f;
    
+    public TurretProjectTile TurretOwner { get; set; }
+    private float _nextAttackTime;
    
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (_enemyTarget != null)
        {
            MoveProjecttile();
            RotateProjetile();
        }
        
    }

    private void MoveProjecttile()
    {
        transform.position = Vector2.MoveTowards(transform.position,_enemyTarget.transform.position,moveSpeed * Time.deltaTime);
        float distanceToTarget = (_enemyTarget.transform.position - transform.position).magnitude;
        if (distanceToTarget < minDistanceToDealDamage)
        {
            _enemyTarget.EnemyHealth.DealDamage(damage);
+            TurretOwner.ResetTurretProjectile();
            ObjectPooler.ReturnToPool(gameObject);
            
        }
    }

    private void RotateProjetile()
    {
        Vector3 enemyPos = _enemyTarget.transform.position - transform.position;
        float angle = Vector3.SignedAngle(transform.up, enemyPos, transform.forward);
        transform.Rotate(0f,0f,angle);
    }

    
    public void SetEnemy(Enemy enemy)
    {
        _enemyTarget = enemy;
        
    }
+    public void ResetProjectile()
+    {
+        _enemyTarget = null;
+        transform.localRotation = Quaternion.identity;
+    }    
    
}



```


# 参考

Quaternion.identity

https://docs.unity3d.com/ja/2021.2/ScriptReference/Quaternion-identity.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3eab9ed2-fb18-bc20-0738-e1d8b9aed742.png)



transform.localRotation

https://docs.unity3d.com/ja/2020.3/ScriptReference/Transform-localRotation.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/62bf3be9-cf8e-ea2e-62ba-f7ea35c14ecd.png)


Section5 26

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23141872#content


github コミット分

https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/d23d07eefdc5b244dd7c8a1944f166a8dda200a5