This is, umm…
This needs a bit of work.
First, relying on Euler Angle-based rotation isn't "bad" but shouldn't be treated as perfectly reliable since that's just the reinterpreted values of the Quaternion-based rotations they're actually using.
Second, the “ticks” defining the length of your day are framerate-dependent. There’s no element accounting for how long a frame takes to execute, so a day will pass much more quickly with a higher framerate.
Third, you’re converting a float to a string, then comparing that string to determine whether a full rotation has been made.
Before worrying about all of that, though, let's get to the reason
*why* you see two day increases at a time.
Well, this happens to coincide with the framerate-dependence, although it would probably just be made MORE apparent if it were framerate-independent.
Although the rotation is set to Vector3.zero at the “end of the rotation”, that has zero influence on the “tick” variable, which is the only other source of rotation being applied. If I’m reading it right, you probably get a day increase on one frame, a frame without an increase, then a frame with an increase again. This would occur because “time” is set first thing during Update(), then your “tick” increase is something on the order of ~0.33333 (degrees) per frame.
Now, how to solve the problem?
Quite frankly, I think this needs a complete overhaul. There are a lot of little issues throughout it, and it could be given both a cleaner presentation in general. This may look a bit complicated, but this is for the sake of minimizing unnecessary calculations:
// Example: Normal Earth clock, but every realtime second = 1 game minute
[SerializeField]
private float fTimeScale = 60f;
[SerializeField]
private int iSecondsPerMinute = 60;
[SerializeField]
private int iMinutesPerHour = 60;
[SerializeField]
private int iHoursPerDay = 24;
// These are updated any time the values above are changed
private float secondsPerDay;
private float degreesPerSecond;
// By using Properties, the important per-frame value(s) can be updated
// any time one of these is changed. These don't work as-is in the editor,
// however, so their fields are Serialized (and otherwise marked as private)
public float timeScale
{
get
{
return fTimeScale;
}
set
{
fTimeScale = value;
UpdateTimePerDay();
}
}
public int secondsPerMinute
{
get
{
return iSecondsPerMinute;
}
set
{
iSecondsPerMinute = value;
UpdateTimePerDay();
}
}
public int minutesPerHour
{
get
{
return iMinutesPerHour;
}
set
{
iMinutesPerHour = value;
UpdateTimePerDay();
}
}
public int hoursPerDay
{
get
{
return iHoursPerDay;
}
set
{
iHoursPerDay = value;
UpdateTimePerDay();
}
}
void Start()
{
// Make immediate use of editor-set values
UpdateTimePerDay();
}
void UpdateTimePerDay()
{
// Example: 60 * 60 * 24 = 86400 seconds in a day
secondsPerDay = secondsPerMinute * minutesPerHour * hoursPerDay;
// 60 * 360 (21600) / 86400 = 0.25
// Alt: 86400 / 60 = 1440 --- 360 / 1440 = 0.25
degreesPerSecond = (timeScale * 360f) / secondsPerDay;
}
void Update()
{
time += degreesPerSecond * Time.deltaTime;
sun.transform.rotation = Quaternion.AngleAxis(time, Vector3.right);
if(time >= 360f)
{
time -= 360f; // Decrease "rotation angle" by a full rotation
day += 1; // Add one day to the counter
dayText.text = string.Format("Day {0}", day.ToString());
}
}