How to switch which weapon I am using while keeping all weapons "active"?

So I have a weapon system that uses at most 3 weapons, where I want only 1 weapon to be usable at a time.

However, I want the weapons to all be “functioning” no matter which weapon I’ve chosen. So let’s say I’ve burned through the ammo on one weapon and it goes into reload, I switch to another weapon, I want that weapon to finish reloading but not be “shoot-able.”

This is for multiple reasons: I have a GUI system that puts the ammo stats of all 3 weapons in one corner of the screen. When one is inactive, it stops updating the GUI until I select it (which I don’t want). It also means that in the case of one weapon type, an overheating weapon which uses a coroutine to govern its cooldown cycles, it stops the cooldown when I switch to another weapon.

By making all the weapons active, but only one at a time “fire-able,” all these issues would be fundamentally solved. I want to use some public static bools because that would make things much easier, but two of the weapons use the exact same script, so I can’t just rename the value in one without changing the other and causing problems.

What could I do to fix this?

The weapon code I’m using (overheating weapon script):

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using TMPro;
    
public class MgGun : MonoBehaviour
{
    //variables

    //private IEnumerator decHeat;

    //bullet
    [SerializeField] GameObject bullet;

    //shoot
    [SerializeField] float shootForce, upwardForce;

    //gun stats
    [SerializeField] float timeBetweenShooting, spread, timeBetweenShots, coolSpeed;
    [SerializeField] int minHeat, maxHeat, decVal, incVal, bulletsPerTap;
    [SerializeField] bool allowButtonHold;
    int overheat, bulletCount;


    //bools
    bool shooting, heating, readyToShoot, cantShoot;



    //references
    [SerializeField] Camera fpsCam;
    [SerializeField] Transform attackPoint;
    [SerializeField] AudioSource firingSource;
    [SerializeField] AudioClip firing;

    //Graphics
    public GameObject muzzleFlash;
    public TextMeshProUGUI ammunitionDisplay;

    //debug
    public bool allowInvoke = true;

    private void Awake()
    {
        cantShoot = false;
        heating = false;
        readyToShoot = true;
        bulletCount = bulletsPerTap;
        //decHeat = DecHeat();
    }

    private void Update()
    {
        
        MyInput();


        //Set ammo display if it exists
        if (ammunitionDisplay != null)
        {
            ammunitionDisplay.SetText(overheat + " / " + maxHeat);
        }

        //now here we decrement
        if ((heating == true) && ((shooting == false) || (cantShoot == true)))
        {
            heating = false;
            StartCoroutine("DecHeat");
        }

       
    }

    private void MyInput()
    {
        //Check if allowed to hold down button and take corresponding input (and check for overheating).
        if (allowButtonHold == true) shooting = Input.GetKey(KeyCode.Mouse0);
        else shooting = Input.GetKeyDown(KeyCode.Mouse0);


        //Shooting
        if ((cantShoot == false) && readyToShoot && shooting && (overheat < maxHeat))
        {
            StopCoroutine("DecHeat");
            Shoot();

        } else if (overheat >= maxHeat && (cantShoot == false))
        { 
            readyToShoot = false;
            cantShoot = true;
            heating = true;
            StopCoroutine("DecHeat");
        }


    }

    private void Shoot()
    {
        readyToShoot = false;

        firingSource.PlayOneShot(firing);

        //Find exact hit position using RayCast
        Ray ray = new Ray(fpsCam.transform.position, fpsCam.transform.forward); //Just a ray through the middle of your screen.
        RaycastHit hit;

        //Check if ray hits something;
        Vector3 targetPoint;
        if (Physics.Raycast(ray, out hit)) targetPoint = hit.point;
        else { targetPoint = ray.GetPoint(500); } //Arbitrarily far away point.

        //Calculate direction from attackPoint to targetPoint.
        Vector3 directionWithoutSpread = targetPoint - attackPoint.position;

        //Calculate Spread
        float x = Random.Range(-spread*overheat, spread*overheat);
        float y = Random.Range(-spread*overheat, spread*overheat);

        //Calculate new direction with spread.
        Vector3 directionWithSpread = directionWithoutSpread + new Vector3(x, y, 0);

        //Instantiate bullet/projectile
        GameObject currentBullet = Instantiate(bullet, attackPoint.position, Quaternion.identity);
        currentBullet.transform.forward = directionWithSpread.normalized;

        //Add forces to the bullet
        currentBullet.GetComponent<Rigidbody>().AddForce(directionWithSpread.normalized * shootForce, ForceMode.Impulse);
        currentBullet.GetComponent<Rigidbody>().AddForce(fpsCam.transform.up * upwardForce, ForceMode.Impulse);

        //Instantiate Muzzle Flash
        if (muzzleFlash != null)
        {
            Instantiate(muzzleFlash, attackPoint.position, Quaternion.identity);
        }

        //If more than one bullets per tap 
        if (bulletsPerTap > 1)
        {
            while (bulletsPerTap > 1)
            {
                Invoke("Shoot", timeBetweenShots);
                bulletsPerTap--;
            }
        }
        bulletsPerTap = bulletCount;

        overheat += incVal; //increment heat
        heating = true; //heat check

        //Invoke ResetShot

        if (allowInvoke)
        {
            Invoke("ResetShot", timeBetweenShooting);
            allowInvoke = false;
        }

    }

    private IEnumerator DecHeat()
    {
        //wait for certain amount of time
        // decrease the value from overheat
        while (overheat != minHeat)
        {
            yield return new WaitForSeconds(1f / coolSpeed);
            overheat = overheat - decVal;
        }


        //Reset appropriate values
        overheat = minHeat;
        readyToShoot = true;
        cantShoot = false;
        yield return null;
    }
   

    private void ResetShot()
    {
        //Allow shooting and Invoke again
        readyToShoot = true;
        allowInvoke = true;
    }
}

The current weaponswitching code I am using:

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

public class WeaponSwitch : MonoBehaviour
{
    [Header("References")]
    [SerializeField] private Transform[] weapons;

    [Header("Keys")]
    [SerializeField] private KeyCode[] keys;

    [Header("Settings")]
    [SerializeField] private float switchTime;

    private int selectedWeapon;
    private float timeSinceLastSwitch;

    private void Start()
    {
        SetWeapons();
        Select(selectedWeapon);

        timeSinceLastSwitch = 0f;
    }

    private void Update()
    {
        int previousSelectedWeapon = selectedWeapon;

        for (int i = 0; i < keys.Length; i++)
        {
            if (Input.GetKeyDown(keys*) && timeSinceLastSwitch >= switchTime) {*

selectedWeapon = i;
}
}

if (previousSelectedWeapon != selectedWeapon) Select(selectedWeapon);

timeSinceLastSwitch += Time.deltaTime;
}

private void Select(int weaponIndex)
{
for (int i = 0; i < weapons.Length; i++)
{
weapons*.gameObject.SetActive(i == weaponIndex);*
}

timeSinceLastSwitch = 0f;

OnWeaponSelected();
}

private void OnWeaponSelected()
{

}

private void SetWeapons()
{
weapons = new Transform[transform.childCount];

for (int i = 0; i < transform.childCount; i++)
{
weapons = transform.GetChild(i);
}

if (keys == null) keys = new KeyCode[weapons.Length];
}
}

很简单。
一个WeaponMgr类,管理所有的武器。
一个WeaponBase基类,描述每一种武器。
将所有武器对象放到管理类中进行管理。