- Home /
Coroutine Countdown Timer being extremely slow
Hey guys so just as a disclaimer I'm relatively new to programming so if I'm making some super obvious mistake please go easy on me
So I'm trying to create a higher customizable Countdown timer for my game, and I want it to be able to be accurate to 0.01 Seconds. I decided I would use the Coroutine method for creating my timer instead of the delta-time one I have seen a couple of times, thinking that this would be a more efficient approach. My game is not very intensive and thus easily runs on hundreds of frames per second, so I thought that using Waitforseconds(0.01) is going to work better because it only needs to be called 100 times every second rather than multiple hundreds. however, I have come into a major issue with my timer. It is EXTREMELY slow. I ran the countdown timer on google and mine side by side starting at 25 seconds and it beat mine out by ten seconds. I even tried adding a artifical delay thinking the waitforseconds function was overshooting, so I would have the time tick down 0.01 seconds when a bit less then that had passed, but my results ended up being sort of inconsistent. Here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TimerScript : MonoBehaviour
{
public Text textDisplay;
private double secondsLeft = 30;
public bool takingAway = false;
private string Texttodisplay;
public int Milisecondsdigits = 2;
void Start()
{
textDisplay = GetComponent<Text>();
Texttodisplay = "00:" + secondsLeft;
if(Milisecondsdigits == 0)
{
Milisecondsdigits = -1;
}
}
void Update()
{
if (takingAway == false && secondsLeft > 0)
{
StopAllCoroutines();
StartCoroutine(TimerTake());
}
if(Texttodisplay.Length > 8 - (Mathf.Abs(Milisecondsdigits -2)))
{
Texttodisplay = Texttodisplay.Substring(0,8- (Mathf.Abs(Milisecondsdigits -2)));
}
textDisplay.text = Texttodisplay;
}
IEnumerator TimerTake()
{
takingAway = true;
yield return new WaitForSeconds(0.01f);
secondsLeft -= 0.01;
if(secondsLeft < 10)
{
Texttodisplay = "00:0" + secondsLeft;
}
else
{
Texttodisplay = "00:" + secondsLeft;
}
takingAway = false;
}
}
could somebody please let me know how I could cause this to become more accurate or why it's acting extremely inaccurate currently :/
Answer by YasanthaPrabath · Aug 30, 2020 at 01:55 AM
If you want to have higher accurate Timer I suggest using update as its much faster than doing in coroutine. Starting coroutines have a cost.
On top of that starting, a new instance of coroutine in every update is a bad approach. Pick one, Either use fully coroutine approach or all in Update() approach.
Additionally try to use stringValue.ToString( "FormatString" ) for formatting which is less garbage generating.
https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-pad-a-number-with-leading-zeros
Read more about string and Garbage, https://answers.unity.com/questions/1334070/how-to-avoid-garbage-with-strings.html
See below my approach for similar work,
public class CountDownTimer : MonoBehaviour
{
[SerializeField]
private Text _TextDisplay;
public void StartCountDown( float seconds )
{
StopCoroutine("IEnuCountDown");
StartCoroutine(IEnuCountDown(_TextDisplay, seconds ));
}
IEnumerator IEnuCountDown( Text textBox, float countDown )
{
float timeLeft = countDown;
while( timeLeft > 0f )
{
yield return new WaitForEndOfFrame();
timeLeft -= Time.deltaTime;
if( timeLeft < 0 )
{
timeLeft = 0;
textBox.text = timeLeft.ToString( "00.##" );
break;
}
else
{
textBox.text = "00.00";
}
}
yield return 1;
}
#if UNITY_EDITOR
/// <summary>
/// https://docs.unity3d.com/ScriptReference/ContextMenu.html
/// </summary>
[ContextMenu("Test Me")]
public void TestMe()
{
StartCountDown( 10f );
}
#endif
}
Your answer
Follow this Question
Related Questions
CountDown Timer Help (Seconds problem) 2 Answers
Format String Minutes:Seconds 3 Answers
Time does not start counting down when need to 1 Answer
Stop and Resume Timer 0 Answers
Start timer with trigger 1 Answer