Tank game mod

Hey guys, I’m trying to develop on top of the Tank game tutorial but I’m having a hard time since it’s my first time scripting.

How can i use a Coroutine to make the tanks have a reload time before being able to shoot again? I’m trying this but it isn’t really working idk why.

These are the extra declarations I made:

public float m_RechargeTime = 2.0f;
private WaitForSeconds m_WaitShoot;
private bool m_RecentlyFired;

For the shooting i’m starting with:

private void Start()
    {
        m_FireButton = "Fire" + m_PlayerNumber;

        m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime;
        m_WaitShoot = new WaitForSeconds (m_RechargeTime);

    }

private void Update()
    {
        m_AimSlider.value = m_MinLaunchForce;

        StartCoroutine (Shooting ());

}

    private IEnumerator Shooting()
    {
        while (m_RecentlyFired)
        {
            yield return null;
        }

        if(m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
        {
            //at max charge, not fired
            m_CurrentLaunchForce = m_MaxLaunchForce;
            Fire ();
        }

And so on.

Then, for the Fire function I’m doing this:

private IEnumerator Fire()
    {
        // Instantiate and launch the shell.
            m_Fired = true;
            Reload();

            Rigidbody shellInstance = Instantiate (m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;

            shellInstance.velocity = m_FireTransform.forward * m_CurrentLaunchForce;

            m_ShootingAudio.Stop ();
            m_ShootingAudio.clip = m_FireClip;
            m_ShootingAudio.Play ();

            m_CurrentLaunchForce = m_MinLaunchForce;
          
    }

    private IEnumerator Reload()
    {
        m_RecentlyFired = true;
        yield return m_WaitShoot;
        m_RecentlyFired = false;
    }

It doesn’t seem to work however. The bool m_RecentlyFired doesn’t seem be to automatically activating. However, If I make it public and manually activate it it will stop the tank from firing, which is good.

Thanks in advance!

Here’s the entire code in case anyone needs to see the full picture:

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

public class TankShooting : MonoBehaviour
{
    public int m_PlayerNumber = 1;      
    public Rigidbody m_Shell;           
    public Transform m_FireTransform;   
    public Slider m_AimSlider;          
    public AudioSource m_ShootingAudio; 
    public AudioClip m_ChargingClip;    
    public AudioClip m_FireClip;        
    public float m_MinLaunchForce = 15f;
    public float m_MaxLaunchForce = 30f;
    public float m_MaxChargeTime = 0.75f;
    public float m_RechargeTime = 2.0f;
    private WaitForSeconds m_WaitShoot;


    private string m_FireButton;        
    private float m_CurrentLaunchForce; 
    private float m_ChargeSpeed;        
    private bool m_Fired;               
    private bool m_RecentlyFired;

    private void OnEnable()
    {
        m_CurrentLaunchForce = m_MinLaunchForce;
        m_AimSlider.value = m_MinLaunchForce;
    }


    private void Start()
    {
        m_FireButton = "Fire" + m_PlayerNumber;

        m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime;
        m_WaitShoot = new WaitForSeconds (m_RechargeTime);

    }


    private void Update()
    {
        // Track the current state of the fire button and make decisions based on the current launch force.
        m_AimSlider.value = m_MinLaunchForce;

        StartCoroutine (Shooting ());

}

    private IEnumerator Shooting()
    {
        while (m_RecentlyFired)
        {
            yield return null;
        }

        if(m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
        {
            // At max charge, not fired.
            m_CurrentLaunchForce = m_MaxLaunchForce;
            Fire ();
        }
        else if(Input.GetButtonDown(m_FireButton))
        {
            // Have we pressed the fire button for the first time?
            m_Fired = false;
            m_CurrentLaunchForce = m_MinLaunchForce;

            m_ShootingAudio.clip = m_ChargingClip;
            m_ShootingAudio.Play();
        }
        else if (Input.GetButton(m_FireButton) && !m_Fired)
        {
            // Holding the fire button, not yet fired
            m_CurrentLaunchForce += m_ChargeSpeed * Time.deltaTime;

            m_AimSlider.value = m_CurrentLaunchForce;
        }
        else if (Input.GetButtonUp(m_FireButton) && !m_Fired)
        {
            // Fire button released, not fired yet
            Fire ();
        }
    }


    private IEnumerator Fire()
    {
        // Instantiate and launch the shell.
            m_Fired = true;
            Reload();

            Rigidbody shellInstance = Instantiate (m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;

            shellInstance.velocity = m_FireTransform.forward * m_CurrentLaunchForce;

            m_ShootingAudio.Stop ();
            m_ShootingAudio.clip = m_FireClip;
            m_ShootingAudio.Play ();

            m_CurrentLaunchForce = m_MinLaunchForce;
          
    }

    private IEnumerator Reload()
    {
        m_RecentlyFired = true;
        yield return m_WaitShoot;
        m_RecentlyFired = false;
    }
}

up

You have some logical problems with the code.
When you start the Coroutine Shooting() from Update(), it will yield until the m_RecentlyFired is false. However, once that happens it will only execute the code after it once. Secondly the Update function is starting a TON of Shooting Coroutines. So Imagine that m_RecentlyFired is true for the next 20 frames. You will end up with 20 Shooting Coroutines all running at the same time and all wiating for m_RecentlyFired to be false. Your better off moving the m_Recently fired check to the Update function and just call Shooting as a regular function

Secondly Fire is just a regular function not a Coroutine so it doesn’t need IEnumerator just void

Finally Reload is a Coroutine and should be one. So you should call it with StartCoroutine(Reload());
Here is your code with the previous things changed:
Fire Code

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

public class TankShooting : MonoBehaviour
{
    public int m_PlayerNumber = 1;
    public Rigidbody m_Shell;
    public Transform m_FireTransform;
    public Slider m_AimSlider;
    public AudioSource m_ShootingAudio;
    public AudioClip m_ChargingClip;
    public AudioClip m_FireClip;
    public float m_MinLaunchForce = 15f;
    public float m_MaxLaunchForce = 30f;
    public float m_MaxChargeTime = 0.75f;
    public float m_RechargeTime = 2.0f;
    private WaitForSeconds m_WaitShoot;


    private string m_FireButton;
    private float m_CurrentLaunchForce;
    private float m_ChargeSpeed;
    private bool m_Fired;
    private bool m_RecentlyFired;

    private void OnEnable()
    {
        m_CurrentLaunchForce = m_MinLaunchForce;
        m_AimSlider.value = m_MinLaunchForce;
    }


    private void Start()
    {
        m_FireButton = "Fire" + m_PlayerNumber;

        m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime;
        m_WaitShoot = new WaitForSeconds(m_RechargeTime);

    }


    private void Update()
    {
        // Track the current state of the fire button and make decisions based on the current launch force.
        m_AimSlider.value = m_MinLaunchForce;
        if (!m_RecentlyFired)
            Shooting();
    }

    private void Shooting()
    {
        if (m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
        {
            // At max charge, not fired.
            m_CurrentLaunchForce = m_MaxLaunchForce;
            Fire();
        }
        else if (Input.GetButtonDown(m_FireButton))
        {
            // Have we pressed the fire button for the first time?
            m_Fired = false;
            m_CurrentLaunchForce = m_MinLaunchForce;

            m_ShootingAudio.clip = m_ChargingClip;
            m_ShootingAudio.Play();
        }
        else if (Input.GetButton(m_FireButton) && !m_Fired)
        {
            // Holding the fire button, not yet fired
            m_CurrentLaunchForce += m_ChargeSpeed * Time.deltaTime;

            m_AimSlider.value = m_CurrentLaunchForce;
        }
        else if (Input.GetButtonUp(m_FireButton) && !m_Fired)
    `    {
            // Fire button released, not fired yet
            Fire();
        }
    }


    private void Fire()
    {
        // Instantiate and launch the shell.
        m_Fired = true;
        StartCoroutine(Reload());

        Rigidbody shellInstance = Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;

        shellInstance.velocity = m_FireTransform.forward * m_CurrentLaunchForce;

        m_ShootingAudio.Stop();
        m_ShootingAudio.clip = m_FireClip;
        m_ShootingAudio.Play();

        m_CurrentLaunchForce = m_MinLaunchForce;

    }

    private IEnumerator Reload()
    {
        m_RecentlyFired = true;
        yield return m_WaitShoot;
        m_RecentlyFired = false;
    }
}

You can do something like so:

bool ReadyToFire = false;
float ReloadTime = 10;
float ReloadRate = 1;

void Update(){
if(!ReadyToFire){
ReloadTime -= Time.deltaTime * RealoadRate;
}
If(ReloadTime <= 0){
ReadyToFire = true;
}
}

Then all You have to.do is ser ReloadTime to 10 everytime player fire.

I would go with this way as well @Bantaru … no need for coroutines for a simple cooldown timer.