Pozostałe odpowiedzi tylko spekulują, więc napisałem prosty projekt Unity i pozwoliłem mu działać przez chwilę. Po kilku godzinach jest to wynik:
UnityEngine.Time.time
dość szybko traci dokładność. Zgodnie z oczekiwaniami, po uruchomieniu gry przez 4 godziny wartości skaczą o 1 milisekundę, a następnie niedokładność wzrasta.
UnityEngine.Time.deltaTime
zachowuje swoją początkową dokładność poniżej milisekund, nawet po kilku godzinach działania Unity. Jest więc praktycznie gwarantowane, że deltaTime
pochodzi od zależnego od platformy licznika wysokiej rozdzielczości (który zwykle przepełnia się po 10-1000 latach). Istnieje niewielkie ryzyko, które deltaTime
na niektórych platformach nadal straci precyzję.
Niedokładność Czasu jest problemem wszystkiego, od czego zależy UnityEngine.Time.time
. Jednym konkretnym przykładem jest rotacja (np. Wiatraka), na której zwykle opiera się UnityEngine.Mathf.Sin(UnityEngine.Time.time*rotationSpeed)
. Jeszcze bardziej problem _Time
polega na jawnym używaniu animacji przez shadery. Jak wysoka musi być niedokładność, zanim zacznie być zauważalna? Dokładność 20-30 ms (2 dni) powinna być punktem, w którym zauważą ludzie, którzy są świadomi problemu i zwracają szczególną uwagę. Po 50-100 ms (5-10 dniach) wrażliwe osoby, które nie wiedzą o problemie, zaczną go rozgryzać. Od 200 do 300 ms (20-30 dni) problem będzie oczywisty.
Do tej pory nie zostały przetestowane dokładność _SinTime
, _CosTime
i Unity_DeltaTime
, więc nie mogę wypowiedzieć się na temat tych.
To jest skrypt, którego użyłem do testowania. Jest on dołączony do UI.Text
elementu, Ustawienia odtwarzacza projektu pozwalają na uruchomienie projektu w tle, a VSync w Ustawieniach jakości jest ustawiony na Co sekundę V Puste:
public class Time : UnityEngine.MonoBehaviour {
void Start () {
LastTime = (double)UnityEngine.Time.time;
StartTime = System.DateTime.Now;
LastPrintTime = System.DateTime.Now;
}
double LastTime;
System.DateTime StartTime;
System.DateTime LastPrintTime;
void Update () {
double deltaTimeError = (double)UnityEngine.Time.deltaTime - ((double)UnityEngine.Time.time - LastTime);
if (System.DateTime.Now - LastPrintTime > System.TimeSpan.FromMilliseconds(1000))
{
GetComponent<UnityEngine.UI.Text>().text = "StartTime: " + StartTime.ToLongTimeString()
+ "\nCurrentTime: " + System.DateTime.Now.ToLongTimeString()
+ "\n\nTime.deltaTime: " + UnityEngine.Time.deltaTime.ToString("0.000000")
+ "\nTime.time - LastTime: " + ((float)(UnityEngine.Time.time - LastTime)).ToString("0.000000")
+ "\nAbsolute Error: " + System.Math.Abs(deltaTimeError).ToString("0.000E0");
LastPrintTime = System.DateTime.Now;
}
LastTime = UnityEngine.Time.time;
}
}
Jeśli zastanawiasz się nad 0.033203
wartością, jestem pewien, że tak naprawdę 0.033203125
ma binarną reprezentację zmiennoprzecinkową 00111101000010000000000000000000
. Zwróć uwagę na wiele 0
s w mantysie.
Obejścia
Większość gatunków nie wymaga obejścia. Większość graczy nawet nie zagra w grę przez 100 godzin, więc inwestowanie pieniędzy w celu rozwiązania problemu, który ludzie zauważą dopiero po hipotetycznym kilku dniach ciągłego grania, jest ekonomicznie nieopłacalne. Niestety nie mogę wymyślić prostego, uniwersalnego obejścia, które naprawia cały problem bez istotnych wad.