Last active
September 1, 2020 02:36
-
-
Save Mantic/f95949565dda92e18a6e5ee843d729f0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.InputSystem; | |
using System.Collections.Generic; | |
public class TowerShooter : MonoBehaviour | |
{ | |
public GameObject FirePoint; | |
public GameObject Projectile; | |
public GameObject Barrel; | |
[SerializeField] private float range = 15f; | |
[SerializeField] private string enemyTag = "Enemy"; | |
[SerializeField] private float ShootRate = 0.5f; | |
[SerializeField] private float RotateSpeed = 10f; | |
private float nextShoot = 0f; | |
private GameObject Target; | |
void Start() | |
{ | |
// Every 0.5 seconds, search for a new target. | |
InvokeRepeating("UpdateTarget", 0f, 0.5f); | |
} | |
// Obtain a new target | |
void UpdateTarget() { | |
// Get a list of all enemies in play. | |
GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag); | |
// We'll save which one is the closest by comparing against this variable. Default to infinity (so anything matches at first). | |
float closestDistance = Mathf.Infinity; | |
// A temp variable holding the closest enemy we find. | |
GameObject newEnemy = null; | |
// Loop through all enemies. | |
foreach (GameObject enemy in enemies) { | |
// Calculate their distance to the tower. | |
float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position); | |
// Only if they're within the tower's shooting range, will we consider them. | |
if(distanceToEnemy <= range) { | |
// If this enemy is closer than our clostest variable, remember it. | |
if(distanceToEnemy < closestDistance) { | |
newEnemy = enemy; | |
closestDistance = distanceToEnemy; | |
} | |
} | |
} | |
// If we didn't find a new enemy, set our current Target to null and abort. | |
if(newEnemy == null) { | |
Target = null; | |
return; | |
} | |
// If our new target is different from our existing target, look for its "Target" game object | |
// so we know where to aim. If we can't find that game object, aim at its transform position (usually the feet). | |
if(newEnemy != Target) { | |
GameObject targetX = GetChildWithName(newEnemy, "Target"); | |
if(targetX != null) { | |
Target = targetX; | |
} else { | |
Target = newEnemy; | |
} | |
} | |
} | |
public void Fire() { | |
// Instantiate a projectile from the firepoints position and orientation. | |
// FirePoint is a gameobject on the tower position where it shoots from. | |
Instantiate(Projectile, FirePoint.transform.position, FirePoint.transform.rotation); | |
} | |
private void Update() { | |
// If we have a barrel object and have a target, Lerp towards the target (slowly rotate towards it). | |
if(Barrel != null && Target != null) { | |
Quaternion newRot = Quaternion.LookRotation(Barrel.transform.position - Target.transform.position); | |
Barrel.transform.rotation = Quaternion.Lerp(Barrel.transform.rotation, newRot, Time.deltaTime * RotateSpeed); | |
} | |
// If we have a target, start the shooting process. | |
if(Target != null) { | |
// If next shoot is less than current game time, fire! | |
if(nextShoot < Time.time) { | |
// Do math that tells us if we are pointing at them. -0.993 or less means we are. | |
Vector3 dir = (Target.transform.position - Barrel.transform.position).normalized; | |
float dotProd = Vector3.Dot(dir, Barrel.transform.forward); | |
// Only shoot if we're pointing at them. | |
if(dotProd < -0.993) { | |
// Set the next time we can shoot as "now + shoot rate" | |
nextShoot = Time.time + ShootRate; | |
Fire(); | |
} | |
} | |
} | |
} | |
// While in the editor, this will draw the tower's range so we can easily design the game. | |
private void OnDrawGizmosSelected() { | |
Gizmos.color = Color.red; | |
Gizmos.DrawWireSphere(transform.position, range); | |
} | |
// Used to go through a gameobject's children and find one with a specific name. | |
private GameObject GetChildWithName(GameObject obj, string name) { | |
Transform trans = obj.transform; | |
Transform childTrans = trans. Find(name); | |
if (childTrans != null) { | |
return childTrans.gameObject; | |
} else { | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment