- Home /
Issues with bullet not subtracting properly
I have a bullet set up that is working great except for one thing. I have it set up so that when you fire it subtracts one bullet from the amount available. The issue i have is that when it reaches zero, it does the wait like it is supposed to but after the wait is done and it refreshes the bullets, I am able to fire an enormous amount of bullets before it starts to countdown again. Any help would be greatly appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
using UnityEngine.Networking;
[RequireComponent(typeof(PlayerScript))]
public class PlayerScriptControl : NetworkBehaviour
{
private PlayerScript m_Character;
private bool m_Jump;
private bool m_shoot;
private bool m_throw;
public GameObject bulletPrefab;
private GameObject bullet;
public Transform bulletSpawn;
public BulletDamage b_damage;
public float speed;
public int bulletAmount;
public int bulletMax;
private void Awake()
{
m_Character = GetComponent<PlayerScript>();
b_damage = GetComponent<BulletDamage> ();
}
private void Update()
{
if (!isLocalPlayer)
{
return;
}
bool m_crouch = Input.GetKey(KeyCode.LeftControl);
bool m_aim = Input.GetKey(KeyCode.F);
bool m_melee = Input.GetKey(KeyCode.G);
float h = CrossPlatformInputManager.GetAxis("Horizontal");
bool m_shoot = Input.GetKey(KeyCode.C);
bool m_throw = Input.GetKey(KeyCode.V);
// Pass all parameters to the character control script.
m_Character.Move(h, m_Jump, m_crouch, m_aim, m_melee, m_shoot, m_throw);
m_Jump = false;
if (!m_Jump) {
// Read the jump input in Update so button presses aren't missed.
m_Jump = CrossPlatformInputManager.GetButtonDown ("Jump");
}
if (Input.GetKeyDown (KeyCode.C))
{
CmdFire ();
}
if (bulletAmount <= 0)
{
StartCoroutine(BulletReloadTime());
}
}
private void FixedUpdate()
{
// Read the inputs.
}
[Command]
void CmdFire()
{
if (bulletAmount >= 1)
{
bulletAmount = bulletAmount - 1;
print(bulletAmount);
bullet = (GameObject)Instantiate(bulletPrefab, bulletSpawn.position, bulletSpawn.rotation); // Instantiate the bullet on the server
//bullet.GetComponent<Rigidbody2D> ().velocity = new Vector2 (speed,0); // increase the velocity on the bullet after creation
bullet.GetComponent<Rigidbody2D>().velocity = new Vector2(speed, GetComponent<Rigidbody2D>().velocity.y);
if (m_Character.m_FacingRight == true)
{
bullet.transform.Rotate(0, 0, 0);
}
else
{
bullet.GetComponent<Rigidbody2D>().velocity = new Vector2(-speed, GetComponent<Rigidbody2D>().velocity.y);
//speed = -speed;
bullet.transform.Rotate(0, 180, 0);
}
NetworkServer.Spawn(bullet); // Spawn the bullet prefab on the client
Destroy(bullet, 2.0f);// destroy the bullet after 2 seconds
}
else if (bulletAmount <= 0)
{
return;
}
}
IEnumerator BulletReloadTime()
{
print("wait 5 seconds");
yield return new WaitForSeconds(5);
bulletAmount = bulletMax;
}
}
What do you have the bullet$$anonymous$$ax int variable set to?
Is it possible you start the game with a bullet amount of say 5... but then the bullet max is set to 5555? (obviously hypothetical numbers)
I set the max to 20 and the amount to 20 also to start. It stops like it is supposed to, but for some reason after it reloads, I can fire a ton of bullets again before it starts counting down again.
Answer by Habitablaba · Jun 14, 2017 at 11:46 PM
Once you hit 0 bullets, you're starting the reload coroutine every frame for 5 seconds.
This means that 5 seconds later, when the first reload completes, you're going to have 5 seconds of essentially infinite ammo as it reloads over and over again.
To solve this, you could create a member bool variable called reloading, and set it to true at the start of the coroutine, and false at the end. Then, only call StartCoroutine if not reloading.
At first i thought I understood what you mean by "only call StartCoroutine if not reloading" but then I tried a few things and got a little confused, could you explain that a bit more for me?
Basically you have this in your code
private void Update()
{
// When you hit 0 bullets, youll start about 30+ coroutines/second because bulletAmount gets replenished only after 5 seconds when the first coroutine finishes.
if (bulletAmount <= 0)
{
StartCoroutine(BulletReloadTime());
}
}
IEnumerator BulletReloadTime()
{
print("wait 5 seconds");
yield return new WaitForSeconds(5);
// After 5 seconds had passed, all of those 5*30 coroutines will finish one after the other in a span of about 5 seconds (after the 5 sec delay) and each of them will replenish ammo during that 5 seconds
bulletAmount = bullet$$anonymous$$ax;
}
You have to add a check that stops you from creating more coroutines after you have started one
private bool reloading;
private void Update()
{
if (!reloading && bulletAmount <= 0)
{ StartCoroutine(BulletReloadTime());
}
}
IEnumerator BulletReloadTime()
{
reloading = true;
print("wait 5 seconds");
yield return new WaitForSeconds(5);
bulletAmount = bullet$$anonymous$$ax;
reloading = false;
}
Your answer
Follow this Question
Related Questions
How to avoid speed change in bullets while moving? 1 Answer
Shooting & Animation Problem 1 Answer
Shooting with Limited Ammo 2 Answers
shooting problem with raycasting 1 Answer
bullets don't go forward 1 Answer