Issue with if-statements requiring two conditions.
Hey. So I'm trying to build a rest mechanic where the character falls asleep if they use too much energy, and then regains it while they are sleeping. My plan then was to make a simple Bool of 'is character sleeping' and then use an if statement to kick in the code. However, this doesn't seem to work and I can't figure out why.
The problem seems to be the && X portion, as when I remove that condition the code works and the int increases as it should. Any ideas of how to fix this? I've posted the whole script for clarity but only the //ENERGY is relevant, everything else is working fine.
public class Otto_Data : MonoBehaviour
{
public static int health = 1000;
public static int energy = 1000;
public int smart = 1;
public static int exercise = 1;
public int clam = 1000;
//FOOD
public static int foodValue = 500;
public Text foodText;
//Health
private bool isOttoDead;
public Text ottoHealth;
public GameObject dead;
//ENERGY
private bool isOttoSleep;
public Text ottoEnergy;
public GameObject sleep;
protected float energyTimer;
//FOOD
private bool isOttoFull;
private bool isOttoHungry;
private bool isOttoSatited;
public GameObject hungry;
public GameObject full;
protected float foodTimer;
public int delayAmount = 1;
// Start is called before the first frame update
void Start()
{
dead.SetActive(false); //hide otto dead message.
hungry.SetActive(false); //hide 'hungry'.
full.SetActive(false); //hide 'full'
sleep.SetActive(false); // hide sleep
isOttoSleep = false;
}
// Update is called once per frame
void Update()
{
//TIMER
foodTimer += Time.deltaTime;
energyTimer += Time.deltaTime;
//FOODTIMER
if (foodTimer <= delayAmount)
{
foodTimer = 0f;
foodValue--;
foodText.text = "Food: " + foodValue;
}
// HEALTH
ottoHealth.text = "Health: " + health;
if (health == 0)
{
isOttoDead = true;
Debug.Log("Otto is Dead :'(");
dead.SetActive(true);
//gameover
}
// ENERGY
ottoEnergy.text = "energy: " + energy;
if (energy <= 0)
{
isOttoSleep = true;
Debug.Log("Otto is Sleeping :'(");
sleep.SetActive(true);
}
else
{
isOttoSleep = false;
sleep.SetActive(false);
}
if (isOttoSleep == true) //debug
{
Debug.Log("otto is sleeeepping");
}
//energytimer
if (energyTimer <= delayAmount && isOttoSleep == true)
{
energyTimer = 0f;
energy++;
ottoEnergy.text = "energy: " + energy;
Debug.Log("energy increase");
}
// FOODCONDITIONS
if (foodValue > 500)
{
isOttoFull = true;
Debug.Log("Otto is Full");
}
if (isOttoFull == true) //full
{
full.SetActive(true);
}
else
{
full.SetActive(false);
}
if (foodValue < 100) //hungry
{
isOttoHungry = true;
Debug.Log("Otto is Hungry");
}
if (isOttoHungry == true)
{
hungry.SetActive(true);
health--;
}
else
{
hungry.SetActive(false);
}
if (foodValue >= 101 && foodValue <= 499) //Satited
{
isOttoHungry = false;
isOttoFull = false;
isOttoSatited = true;
Debug.Log("Otto is Satited");
hungry.SetActive(false);
full.SetActive(false);
}
}
}
Answer by streeetwalker · Jun 06, 2020 at 03:08 AM
@kenwiggins93, the code logic structure makes it difficult to follow. It's a mess. If it were me I would not be setting sleep and then doing sleep in separate if statements - consolidate them into a set of nested if statements. (the food logic suffers from similar issues).
Here is some pseudo code:
if( ! otto _sleeping ) { // is Otto not sleeping this frame?
if( energy <= 0 ) { // is Otto ready to sleep this frame?
otto _sleeping = true;
sleep_delay = 0;
sleep.SetActive(true); // on the next frame, Otto will sleep.
}
}else{ // Otto is already sleeping during this frame
// Important: because Update is not guaranteed to run at a consistent
// frame rate without using delta time Otto may not sleep for a
// set amount of time, you must use delta time in both
// the sleep delay and the energy calculations!
sleep_delay += Time.deltaTime
// sleep_energy_gain is the amount of energy Otto gains
// per second while sleeping - could be initialized outside of
// the Update function
energy += sleep_energy_gain * Time.deltaTime;
// sleep_max_time is how long should Otto sleep in seconds
// must be initialized outside of the Update function
if( sleep_delay >= sleep_max_time ) { // is Otto done sleeping?
otto _sleeping = false;
sleep.SetActive(false); // on the next frame Otto wakes up
}
}
If Otto can't be killed while he is sleeping (or even if he can), probably an better way to do sleep that requires some kind of timer is to use a coroutine that uses "return yield WaitForSeconds" to effect the delay. That way you can do away with the whole mess