Ammo Reloading

Hey guys. So I started to work on creating a gun for an upcoming “Madness-esq” playground. The actual script I’m making is serving more as a template, then onto specifics with special weapons. The script is being designed to have recoil, bullet projectile, sounds, lighting effects, ammo count system, and all that fun stuff. Most of the variables have been left up to the inspector to input the values for easy attachment to other guns. A lot of this stuff has not been implemented yet.

Here’s the issues I am facing right now:

  • When using " ‘reloadSpeed’ = ‘gunShoot’.length (gunShoot as audio clip) , the reload time is greatly increased. Instead I have to set the exact reload speed in the inspector for it to work. I’d like this to be set to the clips length, so I don’t have to fiddle with timing. Instead I can have the reload speed (and other variables) set to the length of the clip. I feel like this is an easy one, but I’m not figuring it out.

  • When reloading, ammo is not being taken out of the reserve. I can’t wrap my head around that aspect just yet and I can’t properly put it into syntax. Basically, all it does is mimic being taken out of the reserve by keeping track of shots fired, then subtracting the current reserve amount by the shots fired prior to reloading. This obviously has flaws, as you can go into the negatives with reserve ammo.

Here is my script so far. I have the new reload sound code commented out, and replaced with the version that works.

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

public class GeneralGuns : MonoBehaviour
{

    public Text currentClip;
    public Text currentReserve;

    public Transform gunMuzzle;

    public Rigidbody2D gunRigid;

    public GameObject gunProjectile;
    public GameObject bulletShell;
    public GameObject flashSprite;

    public AudioSource gunPref;
    public AudioClip gunShoot;
    public AudioClip gunReload;

    public int curClip;
    public int curReserve;
    private int lastClip;
    public int maxClip;
    private int curRes;

    public float rateOfFire;
    [SerializeField] private float reloadSpeed;
    public float recoilMin;
    public float recoilMax;
    public float randRecoil;

    public bool isSemi;
    public bool isFull;
    private bool isReloading;


    void Start()
    {
        gunRigid = GetComponent<Rigidbody2D> ();
        lastClip = 0;
        isReloading = false;
        //reloadSpeed = gunShoot.length;
    }

    void Update()
    {
        currentClip.text = "" + curClip;
        currentReserve.text = "" + curReserve;
        Fire ();
        ManualReload ();
    }

    void Fire()
    {
        if (Input.GetKeyDown (KeyCode.Space) && !isReloading)
        {

            if (curClip > 0)
            {
                curClip--;
                lastClip++;
                //Diff between clip and reserve(?)
                gunPref.PlayOneShot (gunShoot);
                flashSprite.SetActive (true);
            }
            else
            {
                StartCoroutine (Reload ());
            }

        }
        else
        {
            flashSprite.SetActive (false);
        }
         
    }

    void ManualReload()
    {
        if (Input.GetKeyDown (KeyCode.R) && !isReloading)
        {
            StartCoroutine (Reload ());
        }
    }

    IEnumerator Reload()
    {
        if (curClip != maxClip)
        {
            isReloading = true;
            gunPref.PlayOneShot (gunReload);
            //yield return new WaitForSecondsRealtime (reloadSpeed);
            yield return new WaitForSeconds(reloadSpeed);
            isReloading = false;
            curClip = maxClip;
            curReserve = curReserve - lastClip;
            lastClip = 0;
            Debug.Log ("Reload Time = " + gunReload.length);
        }


    }







}

Looks like you’re well on your way here, but let me make some random suggestions/observations:

  1. divorce the audio clip play time from reloading: a good audio clip has a nice lead-out to silence: it doesn’t just chop off. In the case of reloading, often times there is a resounding “clack” as the magazine is put back in, and you may want to allow the player to fire before that “clack” has died out in terms of its echo. See what I mean with just about any FPS game in existence.

  2. a more-realistic reload “dependency” is often animation: if you are going to show animation of reloading, then that needs to be done before you let the player fire again. A more-complete solution would be to have a ScriptableObject associated with each weapon that says “I play this audio when I reload, I play this animation when I reload, and I deactivate player firing control for this many seconds during reload,” and then those three values can be tuned in a single ScriptableObject instance and kept together.

  3. As for reserve/magazine interactions, I would architect it with two values: bullets in pocket, and bullets in magazine.

  • When you fire, if there is nothing in the magazine, then reload. Otherwise, take one bullet out of the magazine and fire it.

  • When you reload, check how many are in the pocket and make sure it is not more than the size of the magazine. For instance, if you have a 7-shot magazine and 10 shots in your pocket, then you can only load 7 bullets. When you load, subtract 7 from the count in pocket, and add 7 to the count in magazine. If you have a 7-shot magazine and only 2 shots in pocket, then you only put 2 shots into the magazine, and set your pocket count to zero.

  • Finally make sure you handle the case of no bullets left at all: don’t make the player sit through an entire reloading sound just to load zero bullets obviously. :slight_smile:

1 Like

Thanks! So, should I have the bullets and reserve bullets counted as an array then? I do apologize, I am still fairly new to C# and Unity altogether. I definitely see what you mean with the audio clip having sound afterwards.

May I get a little hint or a reference for the ammo portion? Only way I could think of utilizing it that way is to have the bullets in an array, then run checks through it maybe? I have no idea. I just need to know how to take a number away from a variable while also adding it to another one without using some faux method for this to work (?)

Just one of those math concepts that isn’t going through all the way. Absolutely hated math in school.

No, not an array, just a simple integer variable, two of them actually. They are just storing a number that IS the amount of bullets left, both in pocket and in magazine.

Here’s some sample variables you might use to store the bullets:

 int BulletsInPocket;
int BulletsInMagazine;

As for doing the actual programming, perhaps you want to start a little bit further back with some of the basic programming concepts, dealing with variables, flow control, etc. You really want to have a firm grasp on what it means to have a variable represent a value, and write code that modifies that variable by adding or subtracting from it, as well as makes meaningful decisions based on that variable.

This link at the top: Learn has a lot of good stuff in a Unity context.

As an aside on your original array question, if you think of variable as a “container” that contains things like numbers (i.e., the number of bullets you have), then an array is generally speaking simply a bunch of those containers all in a row, or perhaps in grid, depending on the type of array. That might tell you (for instance) the number of bullets contained in the pockets of each of the players in the entire game world, if that makes sense.