Hello, I have some aspirations of incorporating a Card Game mechanic, and larger levels into my build.
So, when Gary mentioned that the Target Locator could be more efficient, I decided to give it a try… here is my attempt… not sure if it actually is more efficient or not, but Its working well(not causing any errors, and I like the functionality it gives my towers) and I’m happy with it so far.
Edit: Swapped the Particle Effect for the projectile to a Beam, from the asset pack Polygon Arsenal, and added Randomized Damage for each time the beam connects, feels a lot better than it did.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PolygonArsenal;
public class TargetLocator : MonoBehaviour
{
[SerializeField] Transform weapon; //Serialized for Debugging Purposes
[SerializeField] Transform target; //Serialized for Debugging Purposes
[SerializeField] float yOffset = 5f; //allows the Hieght of the projectile to be altered (so it doesnt shoot the ground);
[SerializeField] PolygonBeamStatic projectileParticle; //the Particle System used for the Projectile
[SerializeField] float range = 15f;
[SerializeField] float targetDistance;
[SerializeField] float firingDelay = 1f;
[SerializeField] bool firing = false;
[SerializeField] float minDamage = .1f;
[SerializeField] float maxDamage = 5f;
float damage;
public float Damage { get => damage; }
private void Awake()
{
weapon = transform.GetChild(1);//gets the Second transform child in the GameObject... this could be done with SerializeField,
//or anyway method of getting the transfrom, for the towers weapon. its just initializing weapon.
target = null;
targetDistance = range + 1;
}
void Update()
{
if (target != null)
{
AimWeapon();
if (!target.gameObject.activeInHierarchy) //checks if the current target is still viable
{
FindClosestTarget();
}
CheckRange();
}
if (target == null) //Mainly for initialization purposes, but if for some reason the Target becomes null, deactivates the towers firing, and
// targets the closest enemy.
{
projectileParticle.RemoveBeam();
FindClosestTarget();
}
}
/// <summary>
/// Aims the weapon transform at the current target, if no target looks at (0, yOffset ,0)
/// </summary>
void AimWeapon()
{
if (target != null)
{
targetDistance = Vector3.Distance(transform.position, target.position);
weapon.LookAt(new Vector3(target.position.x, target.position.y + yOffset, target.position.z));
}
else
{ weapon.LookAt(new Vector3(0, yOffset, 0)); }
}
private void CheckRange()
{
if (targetDistance > range)
{ projectileParticle.RemoveBeam();
FindClosestTarget();
}
else if (targetDistance < range)
{
if (!firing)
{
StartCoroutine(Fire());
}
}
}
void SetDamage()
{
damage = UnityEngine.Random.Range(minDamage, maxDamage);
print($"Damage = {damage}");
}
IEnumerator Fire()
{
SetDamage();
projectileParticle.SpawnBeam();
firing = true;
yield return new WaitForSeconds(firingDelay/2);
projectileParticle.RemoveBeam();
yield return new WaitForSeconds(firingDelay/2);
firing = false;
}
/// <summary>
/// Calls FindClosestTarget, and starts the particle system.
/// </summary>
private void GetTarget()
{
FindClosestTarget();
}
/// <summary>
/// Locates all enemies in the scene, determines which is closest to the Tower, and sets the target to that enemy
/// </summary>
void FindClosestTarget()
{
Enemy[] enemies = FindObjectsOfType<Enemy>();
Transform closestTarget = null;
float MaxDistances = Mathf.Infinity;
foreach (Enemy enemy in enemies)
{
float targetDistance = Vector3.Distance(transform.position, enemy.transform.position);
if (targetDistance < MaxDistances)
{
closestTarget = enemy.transform;
MaxDistances = targetDistance;
}
}
target = closestTarget;
if (target != null)
{
Fire();
}
}
}
}```