Como se dice aquí :
Tiempo tiempo
La hora al comienzo de este marco (solo lectura). Este es el tiempo en segundos desde el inicio del juego.
Y como sé, el tiempo se almacena en flotador. Entonces, mi pregunta es ¿qué sucederá cuando el valor del tiempo se vuelva muy grande? ¿Se puede desbordar? ¿Perderá precisión y causará errores? ¿El juego se bloqueará o qué?
Respuestas:
Existe un riesgo real de pérdida de precisión de tiempo al usar un flotador de precisión simple .
Aún conservará la precisión al segundo más cercano durante 97 días . Pero en los juegos a menudo nos importa la precisión en el orden de duración de un cuadro.
Un valor de tiempo de flotación de precisión simple en segundos comienza a perder precisión de milisegundos después de aproximadamente 9 horas .
Eso ya no está fuera del alcance de la posibilidad de una sola sesión de juego, o dejar el juego funcionando "AFK" mientras estás en el trabajo / escuela o durmiendo. (Esta es una de las razones por las que una forma común de probar un juego es ejecutarlo durante la noche y comprobar que todavía funciona correctamente en la mañana)
En las consolas modernas, donde los juegos a menudo se suspenden y se reanudan entre sesiones de juego en lugar de cerrarse por completo, no es inesperado que una "sesión única" desde el punto de vista del juego supere las 9 horas de tiempo de ejecución incluso cuando se juega en ráfagas cortas.
Suponiendo que Unity
deltaTime
se calcule a partir de una fuente de tiempo de mayor precisión, lo que se confirma mediante los experimentos de Peter en otra respuesta, confiar en losdeltaTime
tiempos de escala de cuadro es relativamente seguro (solo tenga cuidado de acumular duraciones muy largas sumandodeltaTime
valores, agregando pequeños incrementos a Un flotador más grande es una receta clásica para la pérdida de precisión, incluso cuando se compensa con algoritmos inteligentes ).Dado que
fixedDeltaTime
mantiene el mismo valor que estableció, en lugar de cambiar dinámicamente de cuadro a cuadro, también puede poner un comportamiento sensible al tiempo en FixedUpdate para obtener garantías más sólidas de consistencia.deltaTime
devolverá automáticamente el delta fijo apropiado en estos métodos. Si bien puede haber una frecuencia de ritmo entre actualizaciones fijas y de cuadro, puede suavizar esto a través de la interpolación .Lo que desea evitar es calcular las duraciones restando una marca de tiempo de otra . Después de horas de juego, esto puede causar una cancelación catastrófica, lo que lleva a una precisión mucho menor que la que se obtiene al principio de la carrera. Si comparar las marcas de tiempo es importante para sus sistemas, puede generar su propio valor de tiempo de mayor resolución utilizando otros métodos, como en
System.Diagnostics.Stopwatch
lugar deTime.time
.fuente
El valor máximo de flotación es 3.40282347 * 10 ^ 38, lo que equivale a 10 ^ 31 años cuando se mide en segundos (o 10 ^ 28 años cuando se mide en milisegundos). Confía en mí, no se desbordará.
Lo único que puede aparecer es la inexactitud. Pero un solo número de coma flotante de precisión tiene una precisión de 7-8 dígitos decimales. Si lo usa para medir segundos, es preciso durante aproximadamente 194 días. Si mide milisegundos, es preciso por solo 4,5 horas. Por lo tanto, depende completamente de la precisión que necesita y es posible que necesite encontrar formas alternativas si necesita ser preciso al milisegundo (que probablemente no lo haga).
fuente
¿Cuánta precisión necesita tu juego?
Un flotante de 32 bits tiene 24 bits de precisión. En otras palabras, en el tiempo t, la precisión es ± 2 -23 × t. (Esto no es exactamente correcto, pero está cerca, y los detalles exactos no son terriblemente interesantes).
Si necesita una precisión de 1 ms, luego de 1 ms ÷ 2 -23 = 8400 s = 2h 20m, un flotador de 32 bits ya no es aceptable. Una precisión de 1 ms no es necesaria para la mayoría de los juegos, pero se considera necesaria para aplicaciones musicales.
Si su juego se ejecuta en un monitor de 144 Hz, y desea gráficos con precisión de cuadro, entonces después de 1 ÷ 144 Hz ÷ 2 -23 = 58000 s = 16h, un flotador de 32 bits ya no es aceptable. 16h es mucho tiempo para ejecutar un juego, pero no es inconcebible. Apuesto a que un porcentaje significativo de nosotros hemos jugado un juego durante 16 horas en un solo tramo, incluso solo porque dejamos el juego corriendo y dormimos un poco. En ese punto, las animaciones y las actualizaciones físicas se reducirían a menos de 144Hz.
Si la Unidad
Time.deltaTime
se calcula a partir de un reloj de mayor precisión, entonces podría usar eso y aún así obtener una precisión completa. No sé si esto es cierto o no.Nota al margen
Los juegos y otros programas en Windows a menudo usan
GetTickCount()
para calcular el tiempo. Como usa un número entero de 32 bits para contar milisegundos, se ajusta aproximadamente cada 50 días, si deja su computadora encendida durante tanto tiempo. Sospecho que muchos juegos se colgarían, fallarían o se comportarían de manera extraña si los jugaras en la marca de 50 días.Los enteros, como los de Windows
GetTickCount()
, corren el riesgo de desbordarse, mientras que los flotantes, como los de UnityTime.time
, corren el riesgo de perder precisión.fuente
Las otras respuestas solo especulan, así que escribí un proyecto simple de Unity y lo dejé correr por un tiempo. Después de un par de horas, este es el resultado:
UnityEngine.Time.time
pierde precisión con bastante rapidez. Como se esperaba, después de ejecutar el juego durante 4 horas, los valores saltan en 1 milisegundo, y la imprecisión aumenta después de eso.UnityEngine.Time.deltaTime
mantiene su precisión inicial de submilisegundos incluso después de que Unity ha estado funcionando durante horas. Por lo tanto, está prácticamente garantizado quedeltaTime
se deriva de un contador de alta resolución dependiente de la plataforma (que generalmente se desborda después de 10-1000 años). Sigue existiendo un pequeño riesgo quedeltaTime
aún perderá precisión en algunas plataformas.La inexactitud del tiempo es un problema para todo lo que depende
UnityEngine.Time.time
. Un ejemplo específico es la rotación (por ejemplo, de un molino de viento), que generalmente se basa enUnityEngine.Mathf.Sin(UnityEngine.Time.time*rotationSpeed)
. Aún más de un problema es_Time
que se usa explícitamente para las animaciones de los sombreadores. ¿Qué tan alta debe ser la inexactitud antes de que comience a ser notable? La precisión de 20-30 ms (2 días) debe ser el punto donde las personas que conocen el problema y prestan mucha atención se darán cuenta. A 50-100 ms (5-10 días) las personas sensibles que no conocen el problema comenzarán a resolverlo. De 200 a 300 ms (20 a 30 días) el problema será obvio.Hasta ahora no he probado la exactitud de
_SinTime
,_CosTime
yUnity_DeltaTime
, así que no puedo comentar sobre ellos.Este es el script que he usado para probar. Se adjunta a un
UI.Text
elemento, la configuración del reproductor del proyecto permite que el proyecto se ejecute en segundo plano y VSync en la configuración de calidad se establece en cada segundo V en blanco:Si se está preguntando sobre el
0.033203
valor, estoy bastante seguro de que es realmente0.033203125
, que tiene una representación binaria de coma flotante00111101000010000000000000000000
. Observe los muchos0
s en la mantisa.Soluciones alternativas
La mayoría de los géneros no necesitan una solución alternativa. La mayoría de los jugadores ni siquiera juegan un juego durante 100 horas en total, por lo que invertir dinero para solucionar un problema que la gente solo notará después de unos pocos días hipotéticos de tiempo de juego continuo no es económicamente viable. Lamentablemente, no puedo encontrar una solución universal simple que solucione la totalidad del problema sin acarrear algunos inconvenientes significativos.
fuente