- Home /
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[i]) && 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[i].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[i] = transform.GetChild(i);
}
if (keys == null) keys = new KeyCode[weapons.Length];
}
}
Answer by limnico · Apr 17 at 04:18 AM
很简单。 一个WeaponMgr类,管理所有的武器。 一个WeaponBase基类,描述每一种武器。 将所有武器对象放到管理类中进行管理。
Your answer
