An Interesting Observation [And a possible error in the lecture itself?]

Before anything, first I’d just like to share the code that the instructor guided us through in this lecture:

public class Timer : MonoBehaviour
{
    [SerializeField] float timeToAnswerQuestion = 30f;
    [SerializeField] float timeToShowCorrectAnswer = 10f;

    bool isAnsweringQuestion;
    float timerValue;
    public float fillFraction;
    public bool displayNewQuestion;

    void Update() 
    {
        UpdateTimer();
    }

    public void CancelTimer()
    {
        timerValue = 0;
    }

    void UpdateTimer()
    {
        timerValue -= Time.deltaTime;
        if (isAnsweringQuestion)
        {
            {
                fillFraction = timerValue/timeToAnswerQuestion;
            }
            else
            {
                timerValue = timeToShowCorrectAnswer;
                isAnsweringQuestion = false;
            }
        }
        else
        {
            if (timerValue > 0)
            {
                fillFraction = timerValue/timeToShowCorrectAnswer;
            }
            else
            {
                timerValue = timeToAnswerQuestion;
                isAnsweringQuestion = true;
                displayNewQuestion = true;
            }
        }   
    }
}

One thing that I was confused about in the above code was the variable “timerValue” because although the variable wasn’t assigned a value, the instructor was still subtracting Time.DeltaTime from it.

And when you run the code (after doing the first challenge from the next lecture), there was no error. So this confused me as to how the code was actually working. Thus, in a proper programmer fashion, I filled the code with Log statements. This is the updated code [It’ll be helpful to look at when I show the results]:

public class Timer : MonoBehaviour
{
    [SerializeField] float timeToAnswerQuestion = 30f;
    [SerializeField] float timeToShowCorrectAnswer = 10f;

    bool isAnsweringQuestion;
    float timerValue;
    public float fillFraction;
    public bool displayNewQuestion;

    void Update() 
    {
        Debug.Log("Initial timer Value: " + timerValue);
        Debug.Log("The state of isAnsweringQuestion at the start: " + isAnsweringQuestion);
        UpdateTimer();
    }

    public void CancelTimer()
    {
        timerValue = 0;
    }

    void UpdateTimer()
    {
        timerValue -= Time.deltaTime;
        Debug.Log("Timer Value when first subtracted: " + timerValue);
        if (isAnsweringQuestion)
        {
            Debug.Log("The Player is Answering Question");
            if (timerValue > 0)
            {
                Debug.Log("The Player is Answering the Question & timer > 0");
                fillFraction = timerValue/timeToAnswerQuestion;
            }
            else
            {
                Debug.Log("The Player is Answering the Question & timer < 0");
                timerValue = timeToShowCorrectAnswer;
                isAnsweringQuestion = false;
            }
        }
        else
        {
            Debug.Log("The Player is Checking the Correct Answer");
            if (timerValue > 0)
            {
                Debug.Log("The Player is Checking the Correct Answer & timer > 0");
                fillFraction = timerValue/timeToShowCorrectAnswer;
            }
            else
            {
                Debug.Log("The Player is Checking the Correct Answer & timer < 0");
                timerValue = timeToAnswerQuestion;
                isAnsweringQuestion = true;
                displayNewQuestion = true;
                Debug.Log("The new question has been loaded and is being displayed");
            }
        }   
    }
}

As you can see, there are a lot of Log statements. But anyways, the purpose of me doing this was to see what happened when the Update Method runs the first ever time. And this was the result:

[Please refer the code directly above the image to see where each debug statement is if there’s any confusion. That’ll sort of show the flow.]

So the way the way the instructor’s guided script works is that, as expected, the timer value is 0. BUT since the player is currently not answering a question, when the script goes into the UpdateTimer() method, the script goes into the first else statement and then the second else statement (since timerValue < 0) - and thus the timerValue is assigned the timeToAnswerQuestion value (the value we want to set).

That’s why, when we run the script here, we don’t notice any issue because the value of the timer is being set after the first update.

But I do find this approach kind of wrong? Because according to this approach, on the first update, the script actually skips the first question screen and loads and displays the next question (since the displayNextQuestion bool is set to true).

So I decided to fix it and here’s the code for that:

public class Timer : MonoBehaviour
{
    [SerializeField] float timeToAnswerQuestion = 30f;
    [SerializeField] float timeToShowCorrectAnswer = 10f;

    bool isAnsweringQuestion = true;
    float timerValue;
    public float fillFraction;
    public bool displayNewQuestion;

    //This Start method I have added - not in the lecture video.
    void Start() 
    {
        timerValue = timeToAnswerQuestion;
    }

    void Update() 
    {
        UpdateTimer();
    }

    public void CancelTimer()
    {
        timerValue = 0;
    }

    void UpdateTimer()
    {
        timerValue -= Time.deltaTime;
        if (isAnsweringQuestion)
        {
            if (timerValue > 0)
            {
                fillFraction = timerValue/timeToAnswerQuestion;
            }
            else
            {
                timerValue = timeToShowCorrectAnswer;
                isAnsweringQuestion = false;
            }
        }
        else
        {
            if (timerValue > 0)
            {
                fillFraction = timerValue/timeToShowCorrectAnswer;
            }
            else
            {
                timerValue = timeToAnswerQuestion;
                isAnsweringQuestion = true;
                displayNewQuestion = true;
            }
        }   
    }
}

I basically initiliazed isAnswerQuestion as true and assigned the timerValue in the start method. This way the script will first go through the first question and not directly move on to the next question.

Just thought I share this observation because I saw a similar question on the Udemy lecture itself but didn’t have a conclusive answer.

Update: What Gary did was actually the right way to do it [He is the instructor after all so was there any surprise?]

But I have no clue why this is working so i have hours ahead of me trying to understand why accessing the next question directly is working instead of displaying the current question.

I don’t completely get your confusion but if I understood correctly I think it comes from this method and all the other methods it runs.

    void GetNextQuestion()
    {
        if (questions.Count > 0)
        {
            SetButtonState(true);
            SetDefaultButtonSprites();
            GetRandomQuestion();
            DisplayQuestion();
            progressBar.value++;
            scoreKeeper.IncrementQuestionsSeen();
        }
    }

When the game starts you haven’t set the currentQuestion variable, and you don’t want to if you want your game to always be random, so the game sets it and displays it in a random fashion, so you are not accessing the next question, what you are doing is setting the current question, which might be confusing because of the name of that method I copy-pasted.

What I’m trying to say here, is that you cannot skip the first question because there’s no such thing as a first question until after the timer code runs.

@MoonLearns Did you get why Gary’s code works? I still have no idea

Privacy & Terms