Isabella
Isabella

Reputation: 455

Display and count killed enemies in Unity3D C#

I'm new to Unity3D and I am trying to count all the enemies I have killed on runtime and display in OnGUI(). What I did was that for every time the enemy is killed, I am going to increment: enemyKilled. However, when it does... some time in the program... the display decrements and then disappears.

public class ShootableBox : MonoBehaviour {

    Animator anim;
    public int currentHealth = 3;       
    public int enemyKilled;         // Count how many enemies you have killed           
    public float currentHealthLength;

    bool isSinking;                     // To trigger the dead enemy to sink
    public float sinkSpeed = 1f;        // Sink speed

    void Start() {
        anim = GetComponent<Animator>();
        currentHealthLength = Screen.width/2;
        enemyKilled = 0;
    }

    void Update ()
    {   
        // If the enemy should be sinking...
        if(isSinking)
        {
            transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
        }       
    }


    public void Damage(int damageAmount)
    {
        //subtract damage amount when Damage function is called
        currentHealth -= damageAmount;

        //Check if health has fallen below zero
        if (currentHealth <= 0) {
            enemyKilled = enemyKilled + 1;
            //if health has fallen below zero, deactivate it 
            anim.SetTrigger ("isDead");
            //transform.GetComponent<NavMeshAgent> ().Stop ();

            // Find and disable the Nav Mesh Agent.
            GetComponent <NavMeshAgent> ().enabled = false;

            // Find the rigidbody component and make it kinematic (since we use Translate to sink the enemy).
            GetComponent <Rigidbody> ().isKinematic = true;

            Invoke ("StartSinking", 2.5f);

        } else {
            anim.SetTrigger("isHit");
            anim.SetTrigger("isRun2");
        }
    }

    public void StartSinking() {

        // The enemy should now sink.
        isSinking = true;
        // After 2 seconds destory the enemy.
        Destroy (gameObject, 8f);
    }

    // My problem is somewhere on this part
    public void OnGUI() {

        GUI.contentColor = Color.yellow;

        if (enemyKilled != 0) {

            GUI.Box(new Rect(5, 5, currentHealthLength, 20), "Enemies killed: " + enemyKilled );
        }
    }
}

I can already kill the enemy on runtime. I just can't seem to display the correct number of enemies dead right. How can I fix this error? Thank you so much for all of your help.

Upvotes: 1

Views: 4908

Answers (1)

Mr.Bigglesworth
Mr.Bigglesworth

Reputation: 959

This script is on every enemy so you will get each enemy have a different score and it will try to output that to the GUI.

On top of that you actually destroy the object in the StartSinking function, yet it is responsible for displaying the GUI so that will stop once destroyed.

The script responsible for keeping score should be on some form of GameManager class which can't be destroyed or it would lose count. There should also only be one so it keeps an accurate score.

For example you have a class called GameManager and it is attached to a gameobject in the scene. It doesnt matter what kind of gameobject it can just be empty. This is the class that should keep score and display it to the screen.

The enemy script should only be responsible for and control what the enemy does so take out the GUI calls. When an enemy dies you call the GameManager class and tell it that another enemy has died and it can update its score.

public class GameManager : MonoBehaviour{

private int enemyKilled= 0;

  public void UpdateScore()
  {
     enemyKilled++;
  }

   public void OnGUI()
   {
     GUI.contentColor = Color.yellow;
     GUI.Box(new Rect(5, 5, 20, 20), "Enemies killed: " + enemyKilled );
   }
}

Above is an example manager to increase the score each time the UpdateScore method is called. Then it has a OnGui function to display the score.

All the enemy needs is a reference to the GameManager script so you can call the method. This is easy and there are a few methods of doing it. Either make a variable of the type GameManager and search the scene for it or better yet look into creating a static GameManager which can be accessed at all time (the singleton method).

Hope that helps.

Upvotes: 2

Related Questions