Energy System

Hey im developing an android game an i want to integrate an energy system. im using following code (coded by myself), void is runned every second once

void checkEnergy(){
        secondsElapsed = (int)(System.DateTime.Now - System.DateTime.Parse(PlayerPrefs.GetString("time"))).TotalSeconds;

        int energy = secondsElapsed / 59;
        int timeLeft = secondsElapsed % 59;

        if(timeLeft > 49){
            this.GetComponent<UILabel>().text = "More in : 0:0" + (59 - timeLeft).ToString();
        }else{
            this.GetComponent<UILabel>().text = "More in : 0:" + (59 - timeLeft).ToString();
        }
        if(int.Parse(energyLbl.text)<30 && energy > 0){
            if(energy>0 && int.Parse(energyLbl.text) < 30){
                if((int.Parse(energyLbl.text) + energy) < 30){
                    energyLbl.text = ((int.Parse(energyLbl.text) + energy).ToString());
                    PlayerPrefs.SetInt("energy", (int.Parse(energyLbl.text)));
                    energy = 0;
                }else{
                    energyLbl.text = ((30 - int.Parse(energyLbl.text)).ToString());
                    PlayerPrefs.SetInt("energy", (int.Parse(energyLbl.text)));
                    energy = 0;
                }
                PlayerPrefs.SetString("time", System.DateTime.Now.ToString());
            }
        }else{
            if(energy >0){
                energy = 0;
                this.GetComponent<UILabel>().text = "ENERGY FULL";
            }
        }

        energy = 0;
        timeLeft = 0;
    }

im searching hours now for the mistake i made. so everything works really great but when energy is 29 and the minute is running out, it turns to 1 instead to “ENERGY FULL”

I hope you can help me, thanks,
dwiedenau

Yikes. I see a lot of problems here.

You should be caching components like UILabel and using variables to store values, rather than parsing strings.
I would say that storing timestamps and energy values is a poor use of PlayerPrefs. These arn’t preferences, they are gameplay values and you can store them in the MonoBehaviour.

You should be using the internal Time.time variable, rather than parsing System.DateTime. If you pause the game, for example, you’d want energy calculation to pause as well.

Clean code == easy to ready code == easy to debug code.

Okay, that being said, after reading through this script I’m having difficulty figuring out what it is you’re trying to do, but I’m imagining the problem stems from using integers and integer division instead of floats, which allow decimals.

I THINK what you’re trying to is have it so that energy recharges from zero to full in 60 seconds. In which case, this will do the trick:

//I don't know what UILabel is, but I'm assuming it's a custom
//script that accesses a UnityEngine.UI.Text component.
UILabel energyLabel;

float currentEnergy = 0f;
public float maxEnergy = 100f;   //public so you can set it in the inspector.
public float rechargeTime = 60f; //In seconds, for how long it takes to go from 0 to maxEnergy

void Start() {

    energyLabel = GetComponent<UILabel>();

}   

void Update() {

    //Figure out how much energy should recharge this frame.
    float rechargeDelta = (maxEnergy / rechargeTime) * Time.deltaTime;
   
    //Set current energy to be the current energy amount plus the recharge amount, clamped to maxEnergy, so
    //you can't over charge.
    currentEnergy = Mathf.Clamp(currentEnergy + rechargeDelta, 0f, maxEnergy);
   
    //Set the energy label text. We use Mathf.Approximatly() here instead of == because
    //of complications arising from float point precision. You should look that up.
    if (Mathf.Approximatly(currentEnergy, maxEnergy))
        energyLabel.text = "Energy: FULL";
    else
        energyLabel.text = "Energy: "+currentEnergy;
   
}

Hi!
Line 12 and 13 appear to be the same if statement.
Energy will always be positive (until you set it to 0, twice in a row, after which it is not used again)
You will execute line 15 and 16 until energylbl is 29 and energy is 1 (or more), resulting in an increasing number.
When energylbl is 29 and energy is 1(or more) you will execute line 19 and 20 and set it to 30-29 = 1.
You will never reach line 26 as you reset energylbl to 1 before it reaches 30 so line 12(and 13) will always be true, as long as energylbl started below 30.

Perhaps simplifying out all the int.parse code and hardcoded numbers into a variables would make it more clear.

…or use BenZed’s solution.

1 Like