Veljko
Veljko

Reputation: 1

Attack timer stops after killing enemy (when attack script loose target) (Unity)

Hey guys! I have a problem, I have attack script with cooldown and stuff in it, I've created basic combat system, everything works until I kill enemy, it destroys it as intended but then my attack timer stops counting until I select another enemy. Also I keep getting an error until I select first enemy because target field in attack script is empty at start.

Scripts:

Attack Script:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class BasicAttack : MonoBehaviour {

public GameObject target; //target to attack

public int damage;

public float range = 4;
public float attackTimer;
public float cooldown = 2.0f;

public GameObject damageNumber;
public GameObject cooldownImage;
public Text cooldownText;

Targeting t;
UserInterface UI;

void Start () {

    cooldownImage.SetActive(false);

    attackTimer = 0;

    t = FindObjectOfType<Targeting>();
    UI = FindObjectOfType<UserInterface>();
}

void Update () {

    float distance = Vector3.Distance(target.transform.position, transform.position); //calculating distance

    cooldownText.text = attackTimer.ToString("F0");

    if (attackTimer > 0) {
        attackTimer -= Time.deltaTime;
    }
    if (attackTimer <= 0) {
        attackTimer = 0;
    }
    if (Input.GetKeyUp("1")) { //attack key
        if (attackTimer == 0 && distance < range) {
            Attack();
            attackTimer = cooldown;
            //damage numbers
            var clone = (GameObject)Instantiate(damageNumber, t.selectedTarget.GetComponent<EnemyAI>().hitPoint.position, t.myTransform.rotation);
            clone.GetComponent<DamageNumbers>().damageNumber = damage;
        }
        else {
            Debug.Log("Target is out of range!");
        }
    }
    else {
        cooldownImage.SetActive(true);
    }

    if (attackTimer == 0) {
        cooldownImage.SetActive(false);
    }
}

public void Attack() {

        float distance = Vector3.Distance(target.transform.position, transform.position); //calculating distance

        Vector3 dir = (target.transform.position - transform.position).normalized; //calculating direction
        float direction = Vector3.Dot(dir, transform.forward); //calculating direction

        if (distance < range) { //making player not be able to attack if too far

            if (direction > 0) { //making player not be able to attack if target not in front of him
                EnemyHealth eh = (EnemyHealth)target.GetComponent("EnemyHealth"); //getting enemy health
                t.selectedTarget.GetComponent<EnemyHealth>().TakeDamage(-damage); //adjusting enemy health

                UI.infoText.text = "";
            }
            else {
                Debug.Log("Target needs to be in front of you!");
            }
            UI.infoText.text = "";
        }
        else {
            Debug.Log("Target is out of range!");
        }
} //attack
}

EnemyHealth Script:

using UnityEngine;
using System.Collections;

public class EnemyHealth : MonoBehaviour {

public float maxHealth = 100;
public float curHealth = 100;

CombatTargetUI ct;

void Start () {
    ct = FindObjectOfType<CombatTargetUI>();
}

void Update () {
    TakeDamage(0);
}

public void TakeDamage (int ad) {
    curHealth += ad;

    if (curHealth <= 0) {
        curHealth = 0;
        /*ct.HideUI();*/
        Die();
    }
    if (curHealth >= maxHealth) {
        curHealth = maxHealth;
    }
    if (maxHealth <= 1) {
        maxHealth = 1;
    }
}

void Die () {

    StartCoroutine(TimeToDestroy());
}

IEnumerator TimeToDestroy () {
    yield return new WaitForSeconds(0.5f);
    ct.HideUI();
    Destroy(gameObject);
}

}

Targeting Script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Targeting : MonoBehaviour {

public List<Transform> targets;
public Transform selectedTarget;

public Transform myTransform;

CombatTargetUI ct;

void Start () {
    targets = new List<Transform>();
    selectedTarget = null;
    myTransform = transform;

    ct = FindObjectOfType<CombatTargetUI>();

    AddAllEnemies();
}

public void AddAllEnemies () {

    GameObject[] go = GameObject.FindGameObjectsWithTag("Enemy");

    foreach (GameObject enemy in go) {
        AddTarget(enemy.transform);
    }
}

public void AddTarget (Transform enemy) {
    targets.Add(enemy);
}

void SortTargetsByDistance () {

    targets.RemoveAll(target => target == null);
    targets.Sort(delegate(Transform t1, Transform t2) {
        return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
            });
}

void TargetEnemy () {

    if (selectedTarget == null) {
        SortTargetsByDistance();
        selectedTarget = targets[0];
    }
    else {
        int index = targets.IndexOf(selectedTarget);

        if (index < targets.Count - 1) {
            index++;
        }
        else {
            index = 0;
        }
        DeselectTarget();
        selectedTarget = targets[index];
    }
    SelectTarget();
}

void SelectTarget () {

    ct.ShowUI();

    selectedTarget.GetComponent<Renderer>().material.color = Color.red;

    BasicAttack ba = (BasicAttack)GetComponent("BasicAttack");
    ba.target = selectedTarget.gameObject;
}

public void DeselectTarget () {
    if (selectedTarget != null) {
        selectedTarget.GetComponent<Renderer>().material.color = Color.white;
    }

    selectedTarget = null;
}

void Update () {

    if (Input.GetKeyDown(KeyCode.Tab)) {
        TargetEnemy();
    }
}

}

I think that those are all scripts that might cause problem, can anyone help me? I'm desperate. :(

Upvotes: 0

Views: 351

Answers (2)

Jm_
Jm_

Reputation: 1

I think I know what your Timer problems are.

If I have understood correctly, in the Basic Attack class - Start Method, you iniate the timer.

Then, the timer goes down until its 0, and then you can attack.

I think the problem its that, once you have destroyed your enemy, nothing else happens.

I mean, you actually don´t reset the timer once the enemy is dead. That´s why it only works again, when you select another enemy.

When that happens, the BasicAttack class is called from the Targeting class, and thus, the Start method is called again.

I hope it helped.

Regards!

Upvotes: 0

Umair M
Umair M

Reputation: 10750

In beginning of Update method of your Attack Script, add a null check for target object like this:

if(target == null)
{
    return;
}

Upvotes: 0

Related Questions