Search Unity

Trouble accessing a set time from input field

Discussion in 'Scripting' started by KnightRiderGuy, Jan 22, 2020.

  1. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    I'm working on a count down timer but I'm having trouble accessing the time I set in an input field

    I'm calling my timer from update which points to this:
    Code (CSharp):
    1. if (StartCDTimer == true)
    2.         {
    3.             // Start Timer
    4.             CDTimer -= Time.deltaTime;
    5.             seconds = (int)(CDTimer % 60);
    6.             minutes = (int)((CDTimer / 60) % 60);
    7.             hours = (int)(CDTimer / 3600);
    8.             hoursCDTField.text = hours.ToString("00");
    9.             minutesCDTField.text = minutes.ToString("00");
    10.             secondsUI.text = seconds.ToString("00");
    11.         }
    My input fields are numerical but set as strings.
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    What do you mean you're having trouble accessing the time you set?
     
  3. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    even though I have my input field to start my timer from it always just starts from zero
     
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Well, your time remaining is whatever is in the variable CDTimer. If you want to start with a different amount of time, you need to put a different number into that variable.

    If you have a string but you want to interpret it as a number, you may want to use something like float.TryParse(). If the string is more than just a single number (for instance, if it's something like "10:52") then you may need to do something more complicated; either pre-process the string to isolate the information you want, or use a more generalized parsing algorithm.
     
  5. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    it's just coming from two input fields where I just type in up to 2 digits per field, one for hours and the other for minutes:
    like this:
    Code (CSharp):
    1. public InputField hoursCDTField;
    2. public InputField minutesCDTField;
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    OK, so get the value from those fields using expressions like "hoursCDTField.text" and then feed it into a function like int.TryParse or float.TryParse.
     
  7. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Not sure I follow, I've tried a few different combinations but I guess I'm getting either the order or syntax wrong.
     
  8. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    I think it's already converted as the clock time reads what I set it to in my input fields, it's just that when I start the timer it's not using the time already set on the clock, it seems to just start it at all zeros. I should mention that both the hours and seconds are in two different input fields. I think the problem is in here somewhere:
    Code (CSharp):
    1. // CDTimer Timer
    2.     public void CDTimerCalcu()
    3.     {
    4.         if (StartCDTimer == true)
    5.         {
    6.          
    7.             // Start Timer
    8.             CDTimer -= Time.deltaTime;
    9.             seconds = (int)(CDTimer % 60);
    10.             minutes = (int)((CDTimer / 60) % 60);
    11.             hours = (int)(CDTimer / 3600);
    12.             hoursUI.text = hours.ToString("00");
    13.             minutesUI.text = minutes.ToString("00");
    14.             secondsUI.text = seconds.ToString("00");
    15.          
    16.         }
    17.  
    18.     }
    I set the clock time like this:
    Code (CSharp):
    1. // Set Watch Time To Input Fields For CDT Timer
    2.             hoursUI.text = hoursCDTField.text;
    3.             minutesUI.text = minutesCDTField.text;
     
  9. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Where is the code where you are actually setting CDTimer to what was typed in the input fields? All I see is you set some UI Text components to what is in the input fields, but not where you also adjust CDTimer.

    There needs to be some code which parses the input from the input fields, converts that to a float, and sets CDTimer.
     
  10. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Should it not just count down from the time already set on the watch?
     
  11. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    The way your code is written "the watch" is the CDTimer variable itself. So yes your statement is true, the problem is you've skipped the step of setting the watch.
     
  12. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Hmm I thought it would just count down from the time I had set using the input fields... so what am I missing?
     
  13. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Computers are like evil genies: they give you exactly what you ask for, not what you meant. Computers do not have common sense. They will not "get the gist" of your code or infer your goal. They will follow your instructions exactly as you wrote them, to the letter, no matter how ridiculous the result.

    The first code you posted sets all of your fields based on the value of the variable "CDTimer". It doesn't matter what was in those fields before; the ONLY thing that matters is the value stored in that variable.

    The computer does not know that you are trying to enter a number and count down from that. It's just doing what you told it to do.
     
  14. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Here's the disconnect:

    In your code you update the watch by subtracting Time.deltaTime from CDTimer. You then set separate integers for hours/minutes/seconds from the value of CDTimer, and you use those separate variables to update some UI Text components to display the time to the user.

    When you're taking input from the user, you're taking the string values of those input fields and setting those same UI Text components. But the UI Text components are just for displaying the timer to the user, they aren't the timer itself, and the next time you start the watch again it is going to subtract Time.deltaTime from CDTimer, the same ints again, and the UI Text components, all based on the value of CDTimer. Everything in your code runs off CDTimer, so if you want to change the value of the timer from user input, the only thing that actually matters as far as actually setting the timer is setting the CDTimer variable itself.

    Think of it like this. You've got a computer, and you have a monitor. CDTimer is the computer, and the UI Text fields are the monitor. You now want to shut down and restart the computer, so you go to the monitor and press the power button to shut it off, then press the power button to turn it on. Surprise! The computer didn't restart, and it is just displaying the same thing it did before you tried. Why?

    You're effectively doing the same thing here. When you're taking the user input, you're only using the input to update the user friendly display of the timer, but not the timer itself. The timer itself again is the CDTimer variable in your code. Take the input from the input fields, and use that to update CDTimer, since everything else in your watch is driven off the value of CDTimer.
     
    KnightRiderGuy likes this.
  15. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Ahh, I get it so the UI text is just simple being updated by my:
    Code (CSharp):
    1. // Set Watch Time To Input Fields For CDT Timer
    2.                 hoursUI.text = hoursCDTField.text;
    3.                 minutesUI.text = minutesCDTField.text;
    But what you are saying is the real time value is being stored in:
    Code (CSharp):
    1. float CDTimer;
    So how for example would I actually change the value of the float CDTimer with the value from my input fields??
    I do have those set in the inspector to only accept numerical values and only allow 2 digits to be typed into each field, not that I believe they are related in any way to my problem.

    I believe also that I'm storing each value separately according to what I have here:
    Code (CSharp):
    1.  float seconds;
    2.     float minutes;
    3.     float hours;
     
    Last edited: Jan 23, 2020
  16. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    I tried this as an experiment but it still just started my timer at 00:00:00
    Code (CSharp):
    1. float.TryParse(hoursCDTField.text, out hours);
    I keep searching for how to do this but I keep getting either how to convert an int into a string or other unrelated search results.
     
  17. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Heck I've even tried this!!

    Code (CSharp):
    1. float h = hours;
    2. float.TryParse(hoursCDTField.text, out h);
    3. float m = minutes;
    4. float.TryParse(minutesCDTField.text, out m);
     
  18. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    When you did this, did you assign h and m to the text objects? Did you debug h and m to see what values they were?
     
  19. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    I tried:
    Debug.Log(CDTimer);
    At the end of my code and it still said CDTimer was 0?
     
  20. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    I tried this:
    Code (CSharp):
    1. float.TryParse(hoursCDTField.text, out CDTimer);
    2. Debug.Log(CDTimer);
    And in the console it showed that CDTimer was what I had typed into my input field but when I started th timer is still started at all 0's
     
  21. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    I've tried this:
    Code (CSharp):
    1. float.TryParse(hoursCDTField.text, out hours);
    2. CDTimer = hours;
    The debug says the CDTimer is changed but every time I start the timer it just starts at zero.... this is so frustrating, I've been messing with this crap all day for just a stupid timer to try and get the value from a blasted input field!!
     
  22. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    You are treating your CDTimer as a number of seconds. So if "hours" has a value of 2, and you set CDTimer = hours, you have just set your timer to start at 2 seconds. Try multiplying by 3600.

    And for safety, you should ideally be calling TryParse inside of an "if" condition to check whether it worked. Like
    Code (CSharp):
    1. if (float.TryParse(hoursCDTField.text, out hours))
    2. {
    3.     CDTimer = 3600 * hours;
    4. }
    5. else
    6. {
    7.     Debug.LogError("Unable to parse hours field with a value of: " + hoursCDTField.text);
    8. }
     
    Joe-Censored and KnightRiderGuy like this.
  23. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Ah OK, now I think I'm getting somewhere, I tried your example and it at least is now staring my clock at:
    09:0:12
    The :12 I think is just from the system time already on the clock
    But it now starts counting down from that value so getting somewhere ;)
     
  24. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    But what if I need both values converted?
    I tried this but obviously get an error:
    Code (CSharp):
    1. (float.TryParse(hoursCDTField.text + minutesCDTField.text, out hours, minutes))
     
  25. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Make a separate call to TryParse for each string you want to parse.

    Code (CSharp):
    1. float.TryParse(hoursCDTField.text, out hours)
    2. float.TryParse(minutesCDTField.text, out minutes)
    3.  
    4. float totalSeconds = 60 * minutes + 3600 * hours;
     
  26. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    OK tried that and it just set back to all 00:00:00 again??
     
  27. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Maybe instead of just code snippets, show your full script. Tell us also what values you are testing with. Seems like things are just going in circles.
     
  28. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Code (CSharp):
    1. // Reference To The Input Fields For HOURS And Minutes For CDT Setting
    2. public InputField hoursCDTField;
    3. public InputField minutesCDTField;
    4.  
    5. float seconds;
    6. float minutes;
    7. float hours;
    8.  
    9. float CDTimer;
    10.  
    11. // CDTimer
    12. public bool CDTisActive = false;
    13. // CDTimer Active Bool
    14. // Start CDTimer Bool
    15. public bool StartCDTimer = false;
    16.  
    17.  
    18.  
    19. void Update()
    20. {
    21. if (StartCDTimer == true)
    22.             {
    23.                 CDTimerCalcu();
    24.             }
    25. }
    26.  
    27. // CDTimer Timer
    28.     public void CDTimerCalcu()
    29.     {
    30.         if (StartCDTimer == true)
    31.         {
    32.  
    33.             // Start Timer
    34.             CDTimer -= Time.deltaTime;
    35.             seconds = (int)(CDTimer % 60);
    36.             minutes = (int)((CDTimer / 60) % 60);
    37.             hours = (int)(CDTimer / 3600);
    38.             hoursUI.text = hours.ToString("00");
    39.             minutesUI.text = minutes.ToString("00");
    40.             secondsUI.text = seconds.ToString("00");
    41.            
    42.         }
    43.  
    44.     }
    45.  
    46. public void ActivateCDTimerFunction()
    47. {
    48. if (CDTisActive == false)
    49.             {
    50.                 // Activate CDTimer
    51.                 CDTimerST_one.enabled = false;
    52.                 CDTimerST_two.enabled = true;
    53.                 CDTisActive = true;
    54.                 currentStatus = ComLinkStatus.CDTimer;
    55.                 // Set Watch Time To Input Fields For CDT Timer
    56.                 hoursUI.text = hoursCDTField.text;
    57.                 minutesUI.text = minutesCDTField.text;
    58.                 // Update Actual Timer Value
    59.                 // Test
    60.                 if (float.TryParse(hoursCDTField.text, out hours))
    61.                 {
    62.                     CDTimer = 3600 * hours;
    63.                 }
    64.                 if (float.TryParse(minutesCDTField.text, out minutes))
    65.                 {
    66.                     //CDTimer = 60 * minutes;
    67.                 }
    68.                 else
    69.                 {
    70.                     Debug.LogError("Unable to parse hours field with        a value of: " + hoursCDTField.text);
    71. }
    72.  
    73.  
    74.  
    75.  
    76.             }
    77. }
    OK that's all of the relevant parts of it
     
  29. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Where does StartCDTimer get set to true?
     
  30. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    If you say something like

    x = 7;
    x = 3;

    Then when you're done, x has a value of 3. The fact that you set it to 7 first makes absolutely no difference, because afterwards you threw away that value and set it to 3. Right?

    So what happens when you do this?

    CDTimer = 3600 * hours;
    CDTimer = 60 * minutes;




    Also, you broke your "else".
     
  31. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Also, a suggestion. Convert the hours into seconds. Convert the minutes into seconds, add them together and set CDTimer equal to the total. Then use timespan.

    Code (CSharp):
    1.  
    2. TimeSpan CDTimerSpan = TimeSpan.FromSeconds(CDTimer);
    3.         Debug.Log(CDTimerSpan.Hours);
    4.         Debug.Log(CDTimerSpan.Minutes);
    5.         Debug.Log(CDTimerSpan.Seconds);
    6.  
     
    Joe-Censored likes this.
  32. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    OK I think this fixed it:
    Code (CSharp):
    1. // Test
    2.                 if (float.TryParse(hoursCDTField.text, out hours) && float.TryParse(minutesCDTField.text, out minutes))
    3.                 {
    4.                     float totalSeconds = 60 * minutes + 3600 * hours;
    5.                     CDTimer = 3600 * hours + 60 * minutes;
    6.                 }
    7.              
    8.                 //
    9.              
    10.                 TimeSpan CDTimerSpan = TimeSpan.FromSeconds(CDTimer);
    11.                 Debug.Log(CDTimerSpan.Hours);
    12.                 Debug.Log(CDTimerSpan.Minutes);
    13.                 Debug.Log(CDTimerSpan.Seconds);
    Now because I'm only setting the hours and minutes my clock tends to keep the system time for the seconds so I need to set those to :00
     
  33. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    No. There is absolutely zero chance this is happening.

    As far as the computer knows, CDTimer is not a timer, it's just a number. You are setting that number based on an equation. The computer is going to do the math and plug in the answer. The computer has no idea that the number represents a time, or that you are starting with hours and minutes but no seconds. The computer only looks at the math.

    You might have problems with other parts of your code that are messing up the value in some way. Or maybe you're just surprised that it always starts at 59 seconds instead of 00 seconds because you aren't thinking about the fact that you decrement the time before you display it. But it's not just deciding to take seconds from some other place because you didn't supply them.

    Intentions don't matter. Only the exact instructions you actually write matter.



    Also, it looks an awful lot like you are copy-pasting example code snippets from this thread without really thinking about why they work or how they should go together. If you do that, then this ceases to be a thread about helping you learn and turns into a thread where exasperated people slowly write your whole dang program FOR you, one line at a time. That's not OK.
     
    Joe-Censored likes this.
  34. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    515
    Well all I need to do was add this little last part on.
    Code (CSharp):
    1. CDTimer = 3600 * hours + 60 * minutes + 0 * seconds;
    because the ststem time DID show up on the time display I also had to add in this:
    Code (CSharp):
    1. secondsUI.text = "00";
    Just so that when I go back to the clock display it actually reads "00"
    All good, it works fine now.
    My trouble was in understanding this bit:
    Code (CSharp):
    1. (float.TryParse(hoursCDTField.text, out hours) && float.TryParse(minutesCDTField.text, out minutes))
    I kept trying to do it in one line without the separation :/