0

Reloading bar problem

So I'm making a top-down tank shooter game and I want to make a better reloading system than it was before. So I came to the idea that I need some king of progress bar. I knew how to make it so I started doing it. The problem is that it doesn't work properly. As I show in the .gif above, the progress bar don't go down when you shoot second time. Because I'm new to unity, I still don't know everything very good. So I came here, maybe someone could help.

EDIT: I just found another problem and maybe an answer why I have this problem. The second time my script tries to reload, my "needTimer" bool is false, thus the progress bar is not going down when it's false. The new question would be why it becomes false instead of true? My reloading script:

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

public class Reload : MonoBehaviour {

    public float ammo;
    public Image progress;
    public bool alreadyReloading;
    public bool needTimer;

    void Start () {
        alreadyReloading = false;
    }
    IEnumerator needtimertime(){
        yield return new WaitForSeconds (6.5f);
        needTimer = false;
    }
    IEnumerator uztaisyt(){
        Debug.Log ("REEELOUUUDING!");
        yield return new WaitForSeconds(6.5f);
        ammo += 1;
        alreadyReloading = false;
    }

    void Update () {
        if (needTimer == true) {
            timer ("");
        }
        if (ammo < 5) {
            if(alreadyReloading == false){
                needTimer = true;
                StartCoroutine(uztaisyt());
                alreadyReloading = true;
            }
        }
        if (progress.fillAmount <= 0) {
            progress.fillAmount = 1.0f; 
        }
    }

    void timer(string tipas){
        progress.fillAmount -=  Time.deltaTime / 6.5f;
        StartCoroutine (needtimertime ());
    }
}
Justasmig
  • 67
  • 8
  • What is value of ammo variable when you trying to shoot second time? – Paweł Marecki Sep 03 '15 at 12:26
  • @Pawel Marecki 4 and goes down everytime you shoot. It is showed in the gif – Justasmig Sep 03 '15 at 13:21
  • Please clarify: _alreadyReloading_ and _needTimer_ are public, are they being called from any other object in the scene? Also, where and how is the _ammo_ field being decremented? If the timing of _ammo_ being decremented is out of sync with the Reload Update() function, that could be a possible culprit. – BgRva Sep 03 '15 at 13:40
  • the both bools are not using in any other script, I set them to public for debugging purposes. You can remove public and nothing will change. Ammo is getting called in other script, called shooting, but only taking value, for easier calling. (like value1 = ...GetComponent....value2;). – Justasmig Sep 03 '15 at 14:22
  • Is there an initial value of _ammo_ that is being set in the Unity editor? – BgRva Sep 03 '15 at 14:38
  • What does the 6.5 signify? – user3071284 Sep 03 '15 at 14:53
  • 6.5 is the amount of time in seconds to wait before the [coroutines](http://docs.unity3d.com/Manual/Coroutines.html) return – BgRva Sep 03 '15 at 14:59
  • That's clear. @Justasmig can you explain your reloading system? – user3071284 Sep 03 '15 at 15:01
  • my reloading system works like this: if ammo is below 5, it reloads one bullet every 6.5 seconds (I will change value for better gameplay), and only reloads one bullet, per time. Before there was system that reloaded after every shot, but I found that not being very good. I just didn't liked it how it work. So I decided to make this reload system. If something's not clear please tell me. – Justasmig Sep 04 '15 at 03:48

2 Answers2

0

When you start the uztaisyt() as a coroutine after shooting the first time (in the animation), needTimer is set to true and in the next Update() call, the needtimertime() coroutine will start. Since both the uztaisyt() and needtimertime() have identical 6.5 second waits, they will not both return on the same frame update because needtimertime() will always be started in the next frame after uztaisyt(). And, since there is no guarantee of the time interval between Update() calls, (see Time and Frame Managment), this interval may be more than expected and needtimertime() could return false in the frame right after uztaisyt() is called after firing the second time.

To ensure that the needtimertime() is always started (if not already running) immediately following a call for uztaisyt() (and called within the same frame update), you could try the following update to Reload script, (basically changes to the Update() method and when/how _isTimerRunning is set).

public class Reload : MonoBehaviour {

  public float ammo;
  public Image progress;

  private bool _alreadyReloading;
  private bool _isTimerRunning;

  void Start () {
      _alreadyReloading = false;
      _isTimerRunning = false;
  }

  IEnumerator needtimertime(){
      yield return new WaitForSeconds (6.5f);
      _needTimer = false;
  }

  IEnumerator uztaisyt(){
      Debug.Log ("REEELOUUUDING!");
      yield return new WaitForSeconds(6.5f);
      ammo += 1;
      _alreadyReloading = false;
  }

  void Update () {
      if (ammo < 5) {
          if(_alreadyReloading == false){                                        
              StartCoroutine(uztaisyt());
              _alreadyReloading = true;

              //this will check for and start the progress bar timer in the same udate call
              //so both coroutines finish on the same frame update
              if(!_isTimerRunning){
                _isTimerRunning = true;
                timer ("");
              }
          }
      }
      if (progress.fillAmount <= 0) {
          progress.fillAmount = 1.0f; 
      }
  }

  void timer(string tipas){
      progress.fillAmount -=  Time.deltaTime / 6.5f;
      StartCoroutine (needtimertime ());
  }
}
BgRva
  • 1,521
  • 12
  • 26
  • I found this method not working, because (I think, my opinion) the _timer()_ is called only once, not giving the progress bar enough time, to go down. (instead of going down it gets the value 0.9967943 and stops). What I think is that it need to be called like I was calling before ( if (needTimer == true) { timer (""); } ), but with this time method to synchronize the start time. – Justasmig Sep 04 '15 at 04:11
0

I found my problem and fixed it. The problem was that needTimer was becoming false. So I found where and removed it.

my new code:

using UnityEngine;

using UnityEngine.UI; using System.Collections;

public class Reload : MonoBehaviour {

public float ammo;
public Image progress;
public bool alreadyReloading;
public bool needTimer;

void Start () {
    alreadyReloading = false;
    needTimer = false;
}

IEnumerator uztaisyt(){
    Debug.Log ("REEELOUUUDING!");
    yield return new WaitForSeconds(6.5f);
    ammo += 1;
    alreadyReloading = false;
}

void Update () {
    if (ammo < 5.0f) {
        if(alreadyReloading == false){
            progress.fillAmount = 1.0f;
            needTimer = true;
            StartCoroutine(uztaisyt());
            alreadyReloading = true;
        }
        if (needTimer == true) {
            timer ("");
        }
    }
}

void timer(string tipas){
    progress.fillAmount -=  Time.deltaTime / 6.5f;
}

}

Justasmig
  • 67
  • 8