Christo Christo - 1 month ago 11
C# Question

Unity: Using multiple timers C#

I have multiple classes that use a countdown timer, but when I use more than one timer, the output returns the same value, not two separate values specific to their own class.

If I use one timer, everything works perfectly with no issues, it is literally just splitting those timers into separate timers.

I'm sure I have missed something simple here, but can't figure out why they are returning the same output.

Edit: clarity -

mfCurrentTime
and
mfTimeTravelling
return the same value, and they should return different values from each timer, but they are merging together as if there is only one timer.

They aren't acting like two separate timers, they are acting as if it is one timer

Edit 2: When used individually, both timers return different values, the correct values that they should be returning. It's only when both timers are running at the same time that the issue occurs.

for example:

mfCurrentTime
will always return the current time elapsed as it is continually calling Countdown Update

mfTimeTravelling
returns the time elapsed when the
bool _mbIsTravelling
is true.

When both classes are active,
mfCurrentTime
is correct, and when the
bool
is
true
for
mbIsTravelling
in the other class, it takes the time of
mfCurrentTime
. The issue is that they should be two completely separate timers, not one timer.

Edit 3: @Abion47's help lead to the discovery that everything is working as it should, I had just not included a flag for the update in the Update method. I was so fixed on the way I was calling Countdown being the issue, when the real error was a massive oversight on my behalf. I added a condition to the update, and everything is fine.

if(_mbIsTravelling)
{
mIsTravellinTimer.Update();
}


-

This class is using a Countdown timer.

public class Level_TimeTaken : MonoBehaviour
{
public EndOfLevelElement UIElement;

[HideInInspector]
public float mfCurrentTime;
[HideInInspector]
public string msTimeTaken;

private bool _mbLevelIsActive;
private Countdown mLevelTime = new Countdown(9999.0f);

void Start()
{
mLevelTime.Reset();
_mbLevelIsActive = true;
}

void Update()
{
mLevelTime.Update();
TimerRunning();
UIElement.GetTimeTaken(msTimeTaken);
}

private void TimerRunning()
{
if (_mbLevelIsActive)
{
mfCurrentTime = mLevelTime.GetTimeElapsed();
msTimeTaken = mfCurrentTime.ToString("#.00");
}
}
}


This class is also using a Countdown timer.

public class Level_DistanceTravelled : MonoBehaviour
{
public EndOfLevelElement UIElement;

[HideInInspector]
public float mfTimeTravelling;
[HideInInspector]
public string msDistanceTravelled;

private bool _mbIsTravelling;
private Countdown mIsTravellinTimer = new Countdown(6000.0f);

void Start()
{
mIsTravellinTimer.Reset();
}

void Update()
{
mIsTravellinTimer.Update();
DistanceTravelling();
UIElement.GetDistanceTravelled(msDistanceTravelled);
}

private void DistanceTravelling()
{
if (GMM.Instance.Input.ShouldLHorizontalKeyLeft() || GMM.Instance.Input.ShouldLHorizontalKeyRight() || GMM.Instance.Input.ShouldLHorizontalAxis() != 0.0f)
{
_mbIsTravelling = true;
}
else
{
_mbIsTravelling = false;
}

if (_mbIsTravelling)
{
// add math for working out distance so the string displays meters spooled
mfTimeTravelling = mIsTravellinTimer.GetTimeElapsed();
msDistanceTravelled = mfTimeTravelling.ToString("#.00");
}
}
}


and Countdown class, (a generic class for handling timers etc) is here

public class Countdown
{
private float _mfCountdownTime;
private float _mfCurrentTime;

public Countdown(float lfCountdownTime)
{
_mfCountdownTime = lfCountdownTime;
_mfCurrentTime = 0f;
}

public void Update()
{
Update(Time.deltaTime);
}

public void Update(float lfTimeStep)
{
_mfCurrentTime += lfTimeStep;
if (_mfCurrentTime > _mfCountdownTime)
{
_mfCurrentTime = _mfCountdownTime;
}
}

public bool IsComplete()
{
return _mfCurrentTime >= _mfCountdownTime;
}

public void SetComplete()
{
_mfCurrentTime = _mfCountdownTime;
}

public void Reset()
{
_mfCurrentTime = 0f;
}

public float GetTimeElapsed()
{
return _mfCurrentTime;
}

public float GetTimeRemaining()
{
return _mfCountdownTime - _mfCurrentTime;
}

public float GetProgress()
{
return Mathf.Clamp01(_mfCurrentTime / _mfCountdownTime);
}
}


Thanks

Answer

In both of your scripts, you are getting the value from GetTimeElapsed. This value is the amount of time that has passed since the Countdown had started, which if both Countdowns were started at the same time would give you the same number.

Perhaps you meant to call GetTimeRemaining, which returns a value that takes the total time given into account? Or maybe GetProgress?