Ammo counter Displaying negative number

I’m very new to C sharp in unity, At the moment I’m making and R type game. My spaceship has four settings for its gun.

1)Single shot mode, fires one bullets
2) Double shot mode, fires two bullets
3) Blast mode, fires four bullets
4) Machine gun mode, fires eight bullets

The problem I have if the player has seven bullets and uses machine gun mode, he will fire eight bullets the ammo counter will display -1.

What I want to happen if the player doesn’t have enough bullets for the mode, he will not be able to use that mode, and also the ammo counter doesn’t display negative numbers.

I have written some c# code which does the job, but feels a bit brute force. I was wondering is there a more concise way of writing it.

C# code below

public float ammo1 = 1; //Singleshot Mode
    public float ammo2 = 2; //Double shot Mode
    public float ammo3 = 4; //Blast mode
    public float ammo4 = 8; //Machine gun mode

    public float ammoMax = 10;

    public bool onOff1; // ON Off for Singleshot Mode
    public bool onOff2; // ON Off for Double shot Mode
    public bool onOff3; // ON Off for Blast mode
    public bool onOff4; // ON Off for Machine gun mode

    public Text AmmoDis;

    // Use this for initialization
    void Start () {
       
    }

    /// Update is called once per frame
    void Update () {
        Debug.Log ( "ammoMax " + ammoMax);

        //Singleshot Mode

        if(!onOff1 && Input.GetKeyDown(KeyCode.H)){
        ammoMax -= ammo1;
        }

        if (!onOff1 && ammoMax == 0){
        onOff1 = true;
            Debug.Log ( "it wook ");
        }

        // Double shot Mode

        if(!onOff2 && Input.GetKeyDown(KeyCode.J)){
        ammoMax -= ammo2;
        }

        if (!onOff2 && ammoMax == 1){
        onOff2 = true;
            Debug.Log ( "it wook2 ");
        }

        if (!onOff2 && ammoMax == 0){
        onOff2 = true;
            Debug.Log ( "it wook2 ");
        }

        //Blast mode

        if(!onOff3 && Input.GetKeyDown(KeyCode.K)){
        ammoMax -= ammo3;
        }

        if (!onOff3 && ammoMax == 1){
        onOff3 = true;
            Debug.Log ( "it wook3 ");
        }

        if (!onOff3 && ammoMax == 2){
        onOff3 = true;
            Debug.Log ( "it wook3 ");
        }

        if (!onOff3 && ammoMax == 3 ){
        onOff3 = true;
            Debug.Log ( "it wook3 ");
        }

        if (!onOff3 && ammoMax == 0){
        onOff3 = true;
            Debug.Log ( "it wook3 ");
        }

        //Machine gun mode

        if(!onOff4 && Input.GetKeyDown(KeyCode.L)){
        ammoMax -= ammo4;
        }

        if (!onOff4 && ammoMax == 1){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        if (!onOff4 && ammoMax == 2){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        if (!onOff4 && ammoMax == 3 ){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        if (!onOff4 && ammoMax == 4 ){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        if (!onOff4 && ammoMax == 5 ){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        if (!onOff4 && ammoMax == 6 ){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        if (!onOff4 && ammoMax == 7 ){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }


        if (!onOff4 && ammoMax == 0){
        onOff4 = true;
            Debug.Log ( "it wook4 ");
        }

        AmmoDis.text = ammoMax.ToString();

}
}

Thanks that easier to read

I cleaned up your code for my own sanity, and your problem was that you didn’t test if you have enough bullets before substarcting them form ammo

public float ammo2 = 2; //Double shot Mode
public float ammo3 = 4; //Blast mode
public float ammo4 = 8; //Machine gun mode

public float ammoMax = 10;

public int gunState; //State of the gun 1:Singleshot, 2:smile:oubleShot, 3:Blast, 4:Machine gun

public Text AmmoDis;

// Use this for initialization
void Start () {
 
}

/// Update is called once per frame
void Update () {
    Debug.Log ( "ammoMax " + ammoMax);

    //Singleshot Mode

    if(gunState != 0 && Input.GetKeyDown(KeyCode.H) && ammoMax >= ammo1){
        ammoMax -= ammo1;
        gunState = 0;
        Debug.Log ( "it wook ");
    }

    // Double shot Mode

    if(gunState != 1 && Input.GetKeyDown(KeyCode.J) && ammoMax >= ammo2){
        ammoMax -= ammo2;
        gunState = 1;
        Debug.Log ( "it wook2 ");
    }

    //Blast mode

    if(gunState != 2 && Input.GetKeyDown(KeyCode.K) && ammoMax >= ammo3){
        ammoMax -= ammo3;
        gunState = 2;
        Debug.Log ( "it wook3 ");
    }

    //Machine gun mode

    if(gunState != 3 && Input.GetKeyDown(KeyCode.L) && ammoMax >= ammo4){
        ammoMax -= ammo4;
        gunState = 3;
        Debug.Log ( "it wook4 ");
    }

    AmmoDis.text = ammoMax.ToString();
}

I changed a few things:

  • I replaced the bools with a single state counter
  • I got rid of the ifs with the “==”'s and replaced them with a single “>=” one
  • Converted the two ifs to a single one

As far as making your code more concise, you can make a class which holds the data for each type of weapon, and then use an array of these classes to represent all of your weapons.

[System.Serializable] //this line makes it editable in the inspector
class Weapon {
public string name = "Default";
public KeyCode trigger;
public int ammoPerShot = 1;
public int currentAmmo = 0;
public bool CanBeShot() {
return (currentAmmo >= ammoPerShot);
}
public void UseAmmo() {
currentAmmo = Mathf.Max(currentAmmo - ammoPerShot, 0);
}
}

public Weapon[] allWeapons;

void Update() {
for (int w=0;w<allWeapons.Length;w++) {
if (Input.GetKeyDown(allWeapons[w].trigger) && allWeapons[w].CanBeShot() ) {
Debug.Log("Shot the weapon "+w);
allWeapons[w].UseAmmo();
}
}

In the inspector you can add weapons to your heart’s content, picking their keycodes and renaming them. And you can add new weapons to this without needing to change a bunch of code! There are a number of ways you can handle the weapon firing logic itself, including a GameObject variable in the class (which just gets instantiated), or a UnityEvent, to which you can assign a function in the main script (if you need additionally unique logic per weapon), or you can simply do some logic based on the weapon’s name - feel free to ask for help on implementing any of these.

Hi StarManta

Thank you for help I am very new to c# your code is at a higher level I can understand.

I simplified my original code down to:

public float ammo1 = 1; //Single shot Mode
    public float ammo2 = 2; //Double shot Mode
    public float ammo3 = 4; //Blast mode
    public float ammo4 = 8; //Machine gun mode

    public bool gunState1; // ON Off for Singleshot Mode
    public bool gunState2; // ON Off for Double shot Mode
    public bool gunState3; // ON Off for Blast mode
    public bool gunState4; // ON Off for Machine gun mode

    public float ammoMax = 10;
    
    //public int gunState; //State of the gun 1:Singleshot, 2:smile:oubleShot, 3:Blast, 4:Machine gun
    
    public Text AmmoDis;
    
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame


      void Update () {
        Debug.Log ( "ammoMax " + ammoMax);
        Debug.Log ( "gunState " + gunState1);
         AmmoDis.text = ammoMax.ToString();
        //Singleshot Mode

        /////1

       if(Input.GetKeyDown(KeyCode.H) && ammoMax >= ammo1)
        {
            ammoMax -= ammo1;
            //Debug.Log ( "it wook ");
        }

        if(Input.GetKeyDown(KeyCode.J) && ammoMax >= ammo2)
        {
            ammoMax -= ammo2;
            //Debug.Log ( "it wook ");
        }

        if(Input.GetKeyDown(KeyCode.K) && ammoMax >= ammo3)
        {
            ammoMax -= ammo3;
            //Debug.Log ( "it wook ");
        }

        if(Input.GetKeyDown(KeyCode.L) && ammoMax >= ammo4)
        {
            ammoMax -= ammo4;
            //Debug.Log ( "it wook ");
        }
        }
       }

It works fine and doesn’t give me any minus numbers

Thank you for your time & effort.

Unity has pretty good coding tutorials on this subject.

Classes and arrays are powerful coding tools, and not too difficult to understand - I highly recommend learning about these.

Hi gorbit99

Thank you for your help You are right I didn’t test if I had enough bullets before substarcting them from the ammo. I don’t know how I missed that, with the project I could not see the wood from the trees.

I don’t know if I’m missing something, but the your code does seem not work properly.

You have converted my bool into int.
At the start of the game gunState int = 0,

//Single shot Mode
if(gunState != 0 ) {
gunState = 0;
}

Single shot mode will not work because if gunState = 0, then gunState is not equal to 0 the if statement will not complete.
The other gun modes work once

gunState int = 2,
if(gunState != 3 ) {
gunState = 3;
}

if gunState = 2, then gunState is equal to 3 if statement works once.

Second, key press gunState = 2, then gunState is equal to 2 the if statement will not complete.


I simplified my original code down to:

public float ammo1 = 1; //Single shot Mode
    public float ammo2 = 2; //Double shot Mode
    public float ammo3 = 4; //Blast mode
    public float ammo4 = 8; //Machine gun mode

    public float ammoMax = 10;
    
    public Text AmmoDis;
    
     void Update () {
     Debug.Log ( "ammoMax " + ammoMax);
     AmmoDis.text = ammoMax.ToString();

       if(Input.GetKeyDown(KeyCode.H) && ammoMax >= ammo1)
        {
            ammoMax -= ammo1;
            //Debug.Log ( "it work1 ");
        }

        if(Input.GetKeyDown(KeyCode.J) && ammoMax >= ammo2)
        {
            ammoMax -= ammo2;
            //Debug.Log ( "it work2 ");
        }

        if(Input.GetKeyDown(KeyCode.K) && ammoMax >= ammo3)
        {
            ammoMax -= ammo3;
            //Debug.Log ( "it work3 ");
        }

        if(Input.GetKeyDown(KeyCode.L) && ammoMax >= ammo4)
        {
            ammoMax -= ammo4;
            //Debug.Log ( "it work4 ");
        }
        }
}

It works fine and doesn’t give me any minus numbers.
Thank you for your time & effort and putting me on the right track.

Hi Griff, there are some good answers to your question here, but I just have one question if you fire your machine gun and you only have 7 bullets left, do you want it to not fire at all (which StarMana’s code will do perfectly) or to fire the 7 bullets that are left?

Thank you for your advice, I have enrolled on online course in C#.

Hi Josh

Yes my code stops the player firing machine gun if he only has seven bullets

public float playerAmmoMaxFloat = 7;

public float playerAmmoDamage4 = 8; //Machine gun mode

///Fire4
        if(Input.GetKeyDown(KeyCode.Slash ) && playerAmmoMaxFloat >= playerAmmoDamage4){ //Backslash
            InvokeRepeating("Fire4", 0.000001f, playerFiringRateFloat);
        }
        if(Input.GetKeyUp(KeyCode.Slash)){
            CancelInvoke("Fire4");
        }

void Fire4(){
        if(playerAmmoMaxFloat >= playerAmmoDamage4){
        GameObject beam = Instantiate(playerAmmo4Go, transform.position, Quaternion.identity) as GameObject;
        beam.GetComponent<Rigidbody2D>().velocity = new Vector3(projectileSpeed,0,0);
        AudioSource.PlayClipAtPoint(playerFireSound, transform.position);
        playerAmmoMaxFloat -= playerAmmoDamage4;
        }

My problem was I placed “playerAmmoMaxFloat -= playerAmmoDamage1” in the if statement not “void Fire4()” . Which was a creating a weird loop which gave me minus numbers.