{"id":791,"date":"2015-11-25T10:08:07","date_gmt":"2015-11-25T10:08:07","guid":{"rendered":"http:\/\/faulknermano.com\/blog\/?p=791"},"modified":"2015-11-24T10:35:33","modified_gmt":"2015-11-24T10:35:33","slug":"unity-timerclass","status":"publish","type":"post","link":"http:\/\/faulknermano.com\/blog\/unity-timerclass\/","title":{"rendered":"Unity: TimerClass"},"content":{"rendered":"<p>Ok, for seasoned (or maybe even not-so-seasoned) Unity developers, this is probably nothing. But I have been childishly happy about this TimerClass I&#8217;m trying to implement. It&#8217;s simplicity is what makes it exciting.<\/p>\n<p>The TimerClass that I&#8217;m coding is a self-contained timer whose only requirement is that it is updated per Time.deltaTime; thus it needs to be called at the top of every Update(). This works for me because it&#8217;s neat to see all the timers up in one area instead of spread out through the code.<\/p>\n<p>Before I get into the specific things that I like, this is how\u00a0 the code looks like (written in Unityscript\/Javascript):<\/p>\n<pre>#pragma strict\r\n\r\n\/\/ This TimerClass keeps track of a timer\r\nclass TimerClass\r\n{\r\n\tvar timer_name:String;\r\n\tvar end_time:float = 0; \/\/ the end time before the timer sends a signal to say time is up\r\n\tvar counter: float = 0; \/\/ the counter for time\r\n\tvar switchname:String; \/\/ whether the timer should keep on adding delta time or not\r\n\tvar component:Component;\r\n\tvar expired:boolean = false; \/\/ this notes whether the Timer had been previously started and now has expired; needs StartTimer do make a clean start\r\n\t\/\/ this.GetType().GetField(attrname).SetValue(this,parseInt(str));\r\n\tfunction TimerClass()\r\n\t{\r\n\t\t\r\n\t}\r\n\tfunction TimerClass(tn:String, sn:String, et:float, c:Component)\r\n\t{\r\n\t\ttimer_name = tn;\r\n\t\tswitchname = sn;\r\n\t\tend_time = et;\r\n\t\tcomponent = c;\r\n\t}\r\n\tfunction UpdateTime(val:float)\r\n\t{\r\n\t\tvar timerswitch = component.GetType().GetField(switchname).GetValue(component);\r\n\t\tif(timerswitch == true) \/\/ if the switch is TRUE\r\n\t\t{\r\n\t\t\tif(TimeUp() == false) \/\/ if the time is not up, then keep on adding time to the counter\r\n\t\t\t\tcounter += val;\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcomponent.SendMessage(timer_name+\"_TimeUp\",SendMessageOptions.DontRequireReceiver);\r\n\t\t\t\tEndTimer(); \/\/ end timer itself\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\tfunction IsRunning()\r\n\t{\r\n\t\tvar timerswitch = component.GetType().GetField(switchname).GetValue(component);\r\n\t\treturn(timerswitch); \/\/ if the swtich is on, this means the timer is running\r\n\t}\r\n\tfunction StartTimer()\r\n\t{\r\n\t\t\/\/ this makes the switchname turn on\r\n\t\tcomponent.GetType().GetField(switchname).SetValue(component,true);\r\n\t\tResetTimer();\r\n\t}\r\n\tfunction StopTimer()\r\n\t{\r\n\t\tcomponent.GetType().GetField(switchname).SetValue(component,false);\r\n\t}\r\n\tfunction EndTimer()\r\n\t{\r\n\t\tcomponent.GetType().GetField(switchname).SetValue(component,false);\r\n\t\texpired = true;\r\n\t}\r\n\tfunction ResetTimer() \/\/ returns true if time is up\r\n\t{\r\n\t\tcounter = 0;\r\n\t\texpired = false;\r\n\t}\r\n\tfunction TimeUp() \/\/ returns true if time is up\r\n\t{\r\n\t\treturn(counter &gt;= end_time);\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>The two things that I like about this TimerClass is its feature to query a conditional boolean variable directly from the source Component that instantiated it, and the SendMessage mechanism based on the timer&#8217;s name, which is mandatory.<\/p>\n<p>The class is instantiated in this way:<\/p>\n<p style=\"padding-left: 30px;\"><code>Timer = TimerClass(\"WaitTimer\",\"is_waiting\",5,this);<\/code><\/p>\n<p>The first argument is the name of the timer, and this is concatenated with &#8220;_TimeUp&#8221; in order to form the SendMessage function. In the same script, a function is thus defined:<\/p>\n<p style=\"padding-left: 30px;\"><code><br \/>\nfunction WaitTimer_TimeUp()<br \/>\n{<br \/>\n...<br \/>\n}<br \/>\n<\/code><\/p>\n<p>The second argument is the &#8216;switch&#8217; variable, which is a variable that is <em>local<\/em> to script. Note that it&#8217;s a String, not a variable reference; that&#8217;s because it&#8217;s not possible (for me) in Unityscript\/Javascript to pass variables by reference. However, using <a href=\"http:\/\/forum.unity3d.com\/threads\/access-variable-by-string-name.42487\/\">Net Reflection techniques<\/a> you can retrieve a &#8216;field&#8217; from another Component using literal string.<\/p>\n<p>The third argument is the number of seconds it takes for the timer to end or expire.<\/p>\n<p>The fourth argument is &#8216;this&#8217;, which is the reference to the Component that has instantiated the TimerClass. This Component reference is used to retrieve the field specified in the second argument.<\/p>\n<p>Reflection and SendMessage in action in the UpdateTime() function:<\/p>\n<pre>\tfunction UpdateTime(val:float)\r\n\t{\r\n\t\tvar timerswitch = component.GetType().GetField(switchname).GetValue(component);\r\n\t\tif(timerswitch == true) \/\/ if the switch is TRUE\r\n\t\t{\r\n\t\t\tif(TimeUp() == false) \/\/ if the time is not up, then keep on adding time to the counter\r\n\t\t\t\tcounter += val;\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcomponent.SendMessage(timer_name+\"_TimeUp\",SendMessageOptions.DontRequireReceiver);\r\n\t\t\t\tEndTimer(); \/\/ end timer itself\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n<\/pre>\n<p>This TimerClass has simplified enormously the tracking of timers across the game; I&#8217;m glad that I&#8217;ve actually started addressing this issue early on, as I know that would just get worse down the line if I didn&#8217;t have an elegant solution for it. I&#8217;m sure there&#8217;s still a lot I could improve, but I feel happy to have made a start.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ok, for seasoned (or maybe even not-so-seasoned) Unity developers, this is probably nothing. But I have been childishly happy about this TimerClass I&#8217;m trying to implement. It&#8217;s simplicity is what makes it exciting. The TimerClass that I&#8217;m coding is a self-contained timer whose only requirement is that it is updated per Time.deltaTime; thus it needs [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[52,351],"tags":[],"class_list":["post-791","post","type-post","status-publish","format-standard","hentry","category-game-development","category-unity"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1gtd2-cL","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/posts\/791","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/comments?post=791"}],"version-history":[{"count":1,"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/posts\/791\/revisions"}],"predecessor-version":[{"id":792,"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/posts\/791\/revisions\/792"}],"wp:attachment":[{"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/media?parent=791"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/categories?post=791"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/faulknermano.com\/blog\/wp-json\/wp\/v2\/tags?post=791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}