Search Unity

Code Sample: Countdown Timer

Discussion in 'Scripting' started by phuzzy, Mar 13, 2009.

  1. phuzzy

    phuzzy

    Joined:
    Feb 12, 2009
    Posts:
    31
    Below is an example of a countdown timer I'm reasonably in love with. Thanks to the other forum contributors for getting me started with the initial countdown code! Attach it to a parent/level Game Object for best results. Use the getters/setters to access the internal properties and start/stop the timer. Methods are kept out of the way of other scripts to prevent unintended bugs. Best of all, it lets you call a predefined method when the timer is up to handle what to do then (beep, end the level, turn red, etc.).

    To invoke in another script, which is what you oughta be doing, do the following. Note that this example assumes that the calling script and countdown timer are components of the same Game Object.

    Code (csharp):
    1. var o_countdownTimer : countdownTimer;
    2. var f_timerdone = timerDone;
    3. o_countdownTimer = GetComponent(countdownTimer);
    4. o_countdownTimer.setStartTime(90.0);
    5. o_countdownTimer.setTimerDoneAction(f_timerdone);
    6. o_countdownTimer.setTimerState(true);
    7.  
    8. function timerDone() {
    9.     guiText.text = "done!";
    10. }

    Code (csharp):
    1. //countdownTimer: methods to handle a countdown timer
    2. //it is always assumed that there is a guiText item available for the display output
    3.  
    4. //PRIVATE MEMBERS
    5. private var b_timer_active : boolean; //switch to start/stop timer
    6. private var f_timer_done; //method to be called when timer runs down
    7. private var fl_start_time : float; //start time (in seconds)
    8. private var fl_time_left : float; //time left (in seconds)
    9.  
    10. //PUBLIC METHODS
    11. function getFlRemainingTime() { //get the time remaining on the clock
    12.     return fl_time_left;
    13. }
    14.  
    15. function setTimerDoneAction(f_method_fp) { //set the method to be called when the timer is done
    16.     f_timer_done = f_method_fp;
    17. }
    18.  
    19. function setTimerState(b_active_fp : boolean) { //set the active state of the timer
    20.     b_timer_active = b_active_fp;
    21. }
    22.  
    23. function setStartTime(fl_time_fp : float) { //set the starting value for the countdown
    24.     fl_start_time = fl_time_fp;
    25. }
    26.  
    27. function Update() {
    28.     if (b_timer_active) { //check to see if the timer is "on"
    29.         if (!guiText) { //check for an available GUIText component
    30.             Debug.Log("countdownTimer needs a GUIText component!");
    31.             enabled = false;
    32.             return;
    33.         } else {
    34.             doCountdown(); //decrement the time and send value to GUIText for output
    35.         }
    36.     }
    37. }
    38.  
    39. //PRIVATE METHODS
    40. private function doCountdown() { //
    41.     if (fl_start_time) { //make sure that we had a starting time value before conting down
    42.         fl_time_left = fl_start_time - Time.time;
    43.         fl_time_left = Mathf.Max(0, fl_time_left); //don't let the time fall below 0.0
    44.         guiText.text = outReadableTime(fl_time_left); //display the time to the GUI
    45.         if (fl_time_left == 0.0) { //if time has run out, deactivate the timer and call the followup method
    46.             b_timer_active = false;
    47.             if (f_timer_done) { //only call the followup method if we had one
    48.                 f_timer_done();
    49.             }
    50.         }
    51.     } else {
    52.         Debug.Log("countdownTimer needs a value set for fl_time_left");
    53.     }
    54. }
    55.  
    56. private function outReadableTime(fl_time_fp : float) { //format the floating point seconds to M:S
    57.     var i_minutes : int;
    58.     var i_seconds : int;
    59.     var i_time : int;
    60.     var s_timetext : String;
    61.     i_time = fl_time_fp;
    62.     i_minutes = i_time / 60;
    63.     i_seconds = i_time % 60;
    64.     s_timetext = i_minutes.ToString() + ":";
    65.     s_timetext = s_timetext + i_seconds.ToString();
    66.     return s_timetext;
    67. }
     
  2. lupo

    lupo

    Joined:
    Apr 4, 2009
    Posts:
    43
    Thanks for the contribution, phuzzy - saved me some dev time and will certainly help many others.

    Just a note, at first I couldn't get it to work because I had arbetrarily named the larger script "timer.js". Then, based on error messages, I realized the larger script should be named countdownTimer.js, because it is called by the smaller script. I don't think the name of the smaller script is important.

    The way I set it up in my game is that I created a new empty game object, then created a GUI Text under that, and dropped both scripts onto the GUI Text.

    / Brad
     
  3. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
  4. NathanielEdwards

    NathanielEdwards

    Joined:
    May 17, 2009
    Posts:
    12
    To get numbers like 1:08, 1:07, instead of 1:8, and 1:7, just replace the last two lines with this:

    Code (csharp):
    1. if (i_seconds > 9){
    2.         s_timetext = s_timetext + i_seconds.ToString();
    3.     }
    4. else {
    5.         s_timetext = s_timetext + "0" + i_seconds.ToString();
    6.     }
    7. return s_timetext;
    8.  
     
  5. 3devils

    3devils

    Joined:
    Sep 7, 2009
    Posts:
    60
    Hey Phuzzy,

    thank you for that countdown script!
    I made a small adjustment to your script to take the timeSinceLevelLoad, so the Timer always gets reset when a new scene is loaded. (It was driving me crazy, didn't understand that it takes the time from when the *application* started: http://forum.unity3d.com/viewtopic.php?p=229240 )
    I also added a function for adding seconds to the timer (e.g. PowerUps) and integrated the code by Nathaniel.

    Here is my version:

    Code (csharp):
    1.  
    2. /*
    3. * countdownTimer: methods to handle a countdown timer
    4. * it is always assumed that there is a guiText item available for the display output
    5. *
    6. */
    7.  
    8. /*
    9. *   Private member variables
    10. */
    11. private var b_timer_active : boolean; //switch to start/stop timer
    12. private var f_timer_done; //method to be called when timer runs down
    13. private var fl_start_time : float; //start time (in seconds)
    14. private var fl_time_left : float; //time left (in seconds)
    15. private var fl_time_extra : float;
    16.  
    17. /*
    18. *   Public methods
    19. */
    20. function getFlRemainingTime() { //get the time remaining on the clock
    21.    return fl_time_left;
    22. }
    23.  
    24. function setTimerDoneAction(f_method_fp) { //set the method to be called when the timer is done
    25.    f_timer_done = f_method_fp;
    26. }
    27.  
    28. function setTimerState(b_active_fp : boolean) { //set the active state of the timer
    29.    b_timer_active = b_active_fp;
    30. }
    31.  
    32. function setStartTime(fl_time_fp : float) { //set the starting value for the countdown
    33.    fl_start_time = fl_time_fp;
    34. }
    35.  
    36.  
    37. /*
    38. *   Update
    39. */
    40. function Update() {
    41.    if (b_timer_active) { //check to see if the timer is "on"
    42.       if (!guiText) { //check for an available GUIText component
    43.          Debug.Log("countdownTimer needs a GUIText component!");
    44.          enabled = false;
    45.          return;
    46.       } else {
    47.          doCountdown(); //decrement the time and send value to GUIText for output
    48.       }
    49.    }
    50. }
    51.  
    52.  
    53. /*
    54. *   Adding seconds to the countdown, for "powerUps"
    55. */
    56. function addSeconds( seconds : float ){
    57.     //Debug.Log("Adding " + seconds + " seconds!");
    58.     fl_time_extra += seconds;
    59. }
    60.  
    61.  
    62. /*
    63. * Private methods
    64. */
    65. private function doCountdown() { //
    66.    if (fl_start_time  b_timer_active) { //make sure that we had a starting time value before conting down
    67.       fl_time_left = (fl_start_time - Time.timeSinceLevelLoad) + fl_time_extra;
    68.       fl_time_left = Mathf.Max(0, fl_time_left); //don't let the time fall below 0.0
    69.       guiText.text = outReadableTime(fl_time_left); //display the time to the GUI
    70.       if (fl_time_left == 0.0) { //if time has run out, deactivate the timer and call the followup method
    71.          b_timer_active = false;
    72.          if (f_timer_done) { //only call the followup method if we had one
    73.             f_timer_done();
    74.          }
    75.       }
    76.    } else {
    77.       Debug.Log("countdownTimer needs a value set for fl_time_left");
    78.    }
    79. }
    80.  
    81. private function outReadableTime(fl_time_fp : float) { //format the floating point seconds to M:S
    82.    var i_minutes : int;
    83.    var i_seconds : int;
    84.    var i_time : int;
    85.    var s_timetext : String;
    86.    i_time = fl_time_fp;
    87.    i_minutes = i_time / 60;
    88.    i_seconds = i_time % 60;
    89.    s_timetext = i_minutes.ToString() + ":";
    90.     if (i_seconds > 9){
    91.           s_timetext = s_timetext + i_seconds.ToString();
    92.        }
    93.     else {
    94.           s_timetext = s_timetext + "0" + i_seconds.ToString();
    95.        }
    96.     return s_timetext;
    97. }
    98.  
     
  6. goodhustle

    goodhustle

    Joined:
    Jun 4, 2009
    Posts:
    310
    There's an easier way to do the following - just use the formatting argument to ToString, such as:
    Code (csharp):
    1.  
    2. s_timetext = s_timetext + i_seconds.ToString("D2");
    3.  
    It does seem that since this does string concatenation with the plus operator, it will probably run memory allocations. Not much, but it's something to be aware of. I guess you could either go with mono StringBuilder or you could minimize heap growth by checking to see if the time display has changed before recreating the string - that would reduce the number of allocations from every frame to however many allocs occur in a doCountdown() call per second.

     
  7. mehowe7

    mehowe7

    Joined:
    Dec 30, 2009
    Posts:
    65
    Im creating a game where you control a ball which rolls down a terrain to collect good and bad objects which effect the amount of time you have to complete the terrain. I have used your code so I have a working countdown timer but was wondering if you could help me with a few problems?
    The camera is at the side of the ball not above and swings side to side a bit
    How do you make the time-bonus part work? I have objects tagged as 'correct' and 'wrong' but havent got them to effect the timer. Any help??
     
  8. 3devils

    3devils

    Joined:
    Sep 7, 2009
    Posts:
    60
    @melbabez7: Sorry, I stopped watching this thread.

    Camera: This is most likely related to the axis rotation of your ball object, make sure it's not rotated, set all rotations to 0 and try to figure it out then. I also had that problem once.

    Time bonus: Call the addSeconds() function on the timer object. You need to have it present in the object you are trying to call the function from. If you don't know how, check out the basic scripting information in the documentation.
     
  9. shadowsedge19

    shadowsedge19

    Joined:
    Mar 4, 2010
    Posts:
    12
    I'm having trouble adding these scripts, what should the file name of the 2 scripts be, what component should they be added to, and what component needs to go on the o_countdownTimer getter?
     
  10. Jessw14

    Jessw14

    Joined:
    Jan 31, 2010
    Posts:
    14
    How would I alter this script to make it so the timer counts down from a specified amount of seconds and once it hits zero seconds a new scene is loaded and if there is any input the timer resets itself and begins the countdown again.

    I am trying to make it when a player in the game remains idle after a number of minutes that the game restarts itself.
     
  11. mmuller

    mmuller

    Joined:
    Nov 23, 2010
    Posts:
    92
    Phuzzy/3devils,

    Any way I could utilise this to create a level start countdown. So when the level loads a 3-2-1 counts down then the controls become active. I am already using an instance of this to keep a rundown timer on my game once the player starts...

    I'm guessing that it will need to be in a function Start to call it then a check in Update ?

    Regards,

    mm
     
  12. Karthi

    Karthi

    Joined:
    Jan 20, 2011
    Posts:
    3
    Hi everyone,

    I need to call my gameobject(to run when i play) at specified time . So please some one help me to solve with javascripts.

    Thanks In Advance
    Karthik
     
  13. Drexster

    Drexster

    Joined:
    Feb 3, 2009
    Posts:
    20
    I'm looking to reset the timer from some other event, what would be the best way to go about this.

    Also there are some errors when using #pragma strict, specifically when assigning a method to the f_timer_done var. Not sure how to get around that...