Home > Back-end >  How to make clock logic better in Unity3D?
How to make clock logic better in Unity3D?

Time:12-28

I wrote a code that calculates the elapsed time of the date from Day 1 independent of the real world time. However, two shortcomings were found, and no solution was found.

The first is Time.deltaTime. Time.deltaTime is continuously added to the timeCount parameter to determine that 1 second has passed if it is greater than or equal to 1. This is not exactly 1, so there will be some decimal error than the actual time lapse.

Second, I feel that I use too many if statements. Is there a way to write code more efficiently without compromising readability?

I ask for your opinion on these two issues.

function UpdateTime will be invoked periodically in other code update statements. This is the code I wrote below.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayTime
{
    public int Day { get; private set; }
    public int Hour { get; private set; }
    public int Minute { get; private set; }
    public float Second { get; private set; }
    private float timeCount;

    public PlayTime()
    {
        Day = 0;
        Hour = 0;
        Minute = 0;
        Second = 0;
        timeCount = 0;
    }

    public void UpdateTime()
    {
        timeCount  = Time.deltaTime;
        if (timeCount >= 1)
        {
            timeCount = 0;
            Second  ;
        }
        if (Second >= 60)
        {
            Second = 0;
            Minute  ;
        }
        if (Minute >= 60)
        {
            Minute = 0;
            Hour  ;
        }
        if (Hour >= 24)
        {
            Hour = 0;
            Day  ;
        }
    }
}

CodePudding user response:

Instead of

timeCount = 0;

you could use

timeCount -= 1f;

which already compensates the first inaccuracy.


You could further not use a continuous call at all but rather use absolute time values and only do calculations when you actually access the values

private float initTime;

public PlayTime()
{
    initTime = Time.time;
}

and then rather do something like e.g.

public readonly struct TimeData 
{
    private const int SecondsPerMinute = 60;
    private const int SecondsPerHour = 60 * SecondsPerMinute;
    private const int SecondsPerDay = 24 * SecondsPerHour;

    public int Day {get;}
    public int Hour {get;}
    public int Minute {get;}
    public int Second {get;}

    public TimeData (float time)
    {
        // first round the delta to int -> no floating point inaccuracies 
        // according to your needs you could also use Floor or Ceil here
        var seconds = Mathf.RoundToInt(time);

        // Now we can use the reminder free integer divisions to get the target values 
        Day = seconds / SecondsPerDay;
        seconds -= Day * SecondsPerDay;

        Hour = time / SecondsPerHour;
        seconds -= Hour * SecondsPerHour;

        Minute = seconds / SecondsPerMinute;
        seconds -= Minute * SecondsPerMinute;

        Second = seconds;
    }
}

public TimeData GetTime()
{
    return new TimeData (Time.time - initTime);
}

Time.time is the absolute time in (scaled) seconds since you started the app.


You could basically do the same using e.g. DateTime which basically works the same way but using precise system ticks which makes it also quite expensive though.

for that you would store initially

private DateTime initTime;

public PlayTime()
{
    initTime = DateTime.Now;
}

and then e.g. return

public TimeSpan GetTime()
{
    return DateTime.Now - initTime;
}

which returns a TimeSpan based on the system time and ticks

  • Related