As outras respostas apenas especulam, então escrevi um projeto simples do Unity e o deixei rodar por um tempo. Depois de algumas horas, este é o resultado:
UnityEngine.Time.time
perde a precisão rapidamente. Como esperado, depois de executar o jogo por 4 horas, os valores saltam 1 milissegundo e a imprecisão aumenta depois disso.
UnityEngine.Time.deltaTime
mantém sua precisão inicial de menos de milissegundos, mesmo depois que o Unity estiver em execução por horas. Portanto, é praticamente garantido que deltaTime
é derivado de um contador de alta resolução dependente da plataforma (que geralmente transborda após 10-1000 anos). Ainda existe um pequeno risco que deltaTime
ainda perderá precisão em algumas plataformas.
A imprecisão do tempo é um problema para tudo o que depende UnityEngine.Time.time
. Um exemplo específico é a rotação (por exemplo, de um moinho de vento), que geralmente é baseada UnityEngine.Mathf.Sin(UnityEngine.Time.time*rotationSpeed)
. Ainda mais um problema _Time
é explicitamente usado para animações por shaders. Quão alta a imprecisão precisa ser antes de começar a ser perceptível? A precisão de 20 a 30 ms (2 dias) deve ser o ponto em que as pessoas que estão cientes do problema e prestam muita atenção notarão. Entre 50 e 100 ms (5 a 10 dias), pessoas sensíveis que não conhecem o problema começarão a descobrir o problema. De 200 a 300 ms (20 a 30 dias), o problema será óbvio.
Até agora eu não testei a precisão de _SinTime
, _CosTime
e Unity_DeltaTime
, por isso não posso comentar sobre isso.
Este é o script que eu usei para testar. Ele está anexado a um UI.Text
elemento, as Configurações do Player do projeto permitem que o projeto seja executado em segundo plano, e o VSync nas Configurações de Qualidade é definido como Cada Segundo V em Branco:
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;
}
}
Se você está se perguntando sobre o 0.033203
valor, tenho certeza de que, na verdade 0.033203125
, possui uma representação binária de ponto flutuante 00111101000010000000000000000000
. Observe os muitos 0
s na mantissa.
Soluções alternativas
A maioria dos gêneros não precisa de uma solução alternativa. A maioria dos jogadores nem sequer joga um jogo por 100 horas no total, portanto, investir dinheiro para corrigir um problema que as pessoas só notam após alguns dias hipotéticos de tempo de jogo contínuo não é economicamente viável. Infelizmente, não posso apresentar uma solução alternativa simples e universal que conserte a totalidade do problema sem trazer algumas desvantagens significativas.