- Home /
The question is answered, right answer was accepted
Unit not rotating or shooting closest target with tags
using JetBrains.Annotations; using System.Collections; using System.Collections.Generic; using UnityEngine.AI; using UnityEngine;
public class UnitController : MonoBehaviour { public HealthBar healthBar; public Transform firePoint; public Animator animator; [HideInInspector] public Vector3 target_dest; public List enemy; public GameObject projectile; public float current_unit_health; public static bool shoot = false;
public UnitStats unitStats;
private float timeToFire = 0;
private int randomNumberForSound; // sound variation
private NavMeshAgent navAgent; // for moving
private AudioSource audioSource;
private float distance; // unit stats // right now the distance is basically set to 20
private float fireRate; // unit stats
private float max_unit_health; // unit stats
private GameObject effectToSpawn; // for projectile
public GameObject miniMapIcon;
public void Start()
{
GameObject[] enemyTargets = GameObject.FindGameObjectsWithTag("Enemy");
if (enemyTargets != null)
{
foreach (GameObject go in enemyTargets)
{
enemy.Add(go);
}
}
navAgent = GetComponent<NavMeshAgent>();
// setting unit stats
distance = unitStats.attackRange;
fireRate = unitStats.rateOfFire;
max_unit_health = unitStats.health;
// setting the health bar
healthBar.SetMaxHealth(max_unit_health);
current_unit_health = max_unit_health;
effectToSpawn = projectile;
audioSource = GetComponent<AudioSource>();
}
public void Update()
{
healthBar.SetHealth(current_unit_health);
miniMapIcon.transform.rotation = Quaternion.Euler(90, 0, 0);
if (this.gameObject.transform.position == target_dest)
{
animator.SetBool("Moving", false);
}
foreach (GameObject target in enemy)
{
if (target != null)
{
if (Vector3.Distance(target.transform.position, transform.position) < distance)
{
// looks at enemy but for some reason doesn't look at the closest enemy
Vector3 lookVector = target.transform.position - transform.position;
lookVector.y = transform.position.y;
Quaternion rot = Quaternion.LookRotation(lookVector);
transform.rotation = Quaternion.Slerp(transform.rotation, rot, 1);
shoot = true;
animator.SetBool("Shoot", true);
if (shoot == true && Time.time >= timeToFire)
{
timeToFire = Time.time + 1 / fireRate;
SpawnProjectile();
}
}
else
{
shoot = false;
animator.SetBool("Shoot", false);
}
}
}
if (current_unit_health <= 0)
{
Destroy(this.gameObject);
}
}
public void MoveUnit(Vector3 dest)
{
navAgent.destination = dest;
animator.SetBool("Moving", true);
}
public void Selected(bool IsSelected)
{
transform.Find("Highlight").gameObject.SetActive(IsSelected);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, distance);
}
/* A function that initiates the unit to start shooting projectiles/lasers.
* RNG that will get a new number everytime when the function is called meaning
* that everytime the unit shoots it will play a new clip from the sound script
* so the shooting doesn't so redudant and somewhat more immersive. */
void SpawnProjectile()
{
GameObject projectiles;
randomNumberForSound = Random.Range(1, 4);
if (firePoint != null)
{
FindObjectOfType<AudioManager>().Play(randomNumberForSound);
projectiles = Instantiate(effectToSpawn, firePoint.transform.position, firePoint.transform.rotation);
}
}
}
So far this is my script of what I have (I have some other scripts but found it unnecessary to share for this post. So short story, I'm trying to create an RTS game and so far in my scene (for testing), you start of with 2 units that is yours and 5 enemy units. I already have models and working animations and such. When I get my units close to the enemy and they start to shoot, they don't shoot at the closest enemy and the model just stares at one enemy and doesn't face at supposedly the closest one. I have done some research on some solutions but I tried some out but it just breaks my script. Any suggestions or configurations will help, I'm not really the best at this :p.
Answer by CodesCove · Jun 24, 2020 at 10:41 AM
Your script does not select the closest enemy. It selects all enemies within 20 unit radius. First find the closest enemy (where Distance is smallest) and then go for the rotation.
Thx for this input and I ended up figuring it out the next day when I got some sleep. I decided to take out the foreach statement in the update and ins$$anonymous$$d of using a list of gameobjects I decided to go for a single one that will equal to an array of gameobjects. I just took a script that unity already had and use that and bam, it worked.
I used this function public GameObject FindClosestEnemy() { GameObject[] gos; gos = GameObject.FindGameObjectsWithTag("Enemy"); GameObject closest = null; float distance = $$anonymous$$athf.Infinity; Vector3 position = transform.position; foreach (GameObject go in gos) { Vector3 diff = go.transform.position - position; float curDistance = diff.sqr$$anonymous$$agnitude; if (curDistance < distance) { closest = go; distance = curDistance; } } return closest; }
with my original enemy being a list I turned it singular and made it equal to the function outcome above and then used this
if (enemy != null) { if (Vector3.Distance(enemy.transform.position, transform.position) < distance) { Vector3 lookVector = enemy.transform.position - transform.position; lookVector.y = transform.position.y; Quaternion rot = Quaternion.LookRotation(lookVector); transform.rotation = Quaternion.Slerp(transform.rotation, rot, 5 * Time.deltaTime);
shoot = true;
animator.SetBool("Shoot", true);
if (shoot == true && Time.time >= timeToFire)
{
timeToFire = Time.time + 1 / fireRate;
SpawnProjectile();
}
}
else
{
shoot = false;
animator.SetBool("Shoot", false);
}
}