Comme il est dit ici :
Temps temps
L'heure au début de cette image (lecture seule). C'est le temps en secondes depuis le début de la partie.
Et comme je sais, le temps est stocké dans float. Donc, ma question est ce qui se passera quand la valeur du temps devient très grande? Peut-il déborder? Va-t-il perdre de la précision et causer des bugs? Le jeu va-t-il s'effondrer ou quoi?
Réponses:
L'utilisation d'un flottant à simple précision présente un réel risque de perte de précision temporelle .
Il conservera toujours la précision à la seconde près pendant 97 jours . Mais dans les jeux, la précision dépend souvent de la durée d'une image.
Une valeur de temps flottant simple précision en secondes commence à perdre la précision de la milliseconde après environ 9 heures .
Ce n'est déjà pas possible si une seule session de jeu est possible ou de laisser le jeu en cours d'exécution "AFK" pendant que vous êtes au travail / à l'école ou en train de dormir. (C’est l’une des raisons pour lesquelles un moyen courant de tester un jeu consiste à le lancer du jour au lendemain et à s’assurer qu’il se joue toujours correctement le matin)
Sur les consoles modernes, où les jeux sont souvent suspendus et repris entre les sessions de jeu plutôt que d'être complètement arrêtés, il n'est pas surprenant qu'une "session unique" vue du jeu dépasse 9 heures de temps d'exécution, même si elle est jouée en rafales brèves.
En supposant que l'Unity
deltaTime
soit calculé à partir d'une source de temps d'une plus grande précision, ce que corroborent les expériences de Peter dans une autre réponse; ildeltaTime
est relativement sûr de s'en remettre à des minuteries d'échelle (vous devez simplement éviter de cumuler desdeltaTime
valeurs très longues en ajoutant un grand flottant est une recette classique pour la perte de précision, même lorsque vous compensez avec des algorithmes avertis ).Dans la mesure où
fixedDeltaTime
conserve la même valeur que vous définissez, plutôt que de changer dynamiquement d'une image à l'autre, vous pouvez également définir un comportement sensible au minutage dans FixedUpdate pour obtenir des garanties de cohérence plus solides.deltaTime
renverra automatiquement le delta fixe approprié dans ces méthodes. Bien qu'il puisse y avoir une fréquence de battement entre les mises à jour fixes et les mises à jour d'image, vous pouvez la lisser par interpolation .Ce que vous voulez éviter, c'est calculer des durées en soustrayant un horodatage d'un autre . Après des heures de jeu, cela peut entraîner une annulation catastrophique et une précision bien inférieure à celle que vous obtenez au début de la course. Si la comparaison des horodatages est importante pour vos systèmes, vous pouvez générer votre propre valeur de temps de résolution supérieure en utilisant d'autres méthodes, comme
System.Diagnostics.Stopwatch
au lieu deTime.time
.la source
La valeur maximale de float est 3,40282347 * 10 ^ 38, ce qui correspond à 10 ^ 31 ans en secondes (ou à 10 ^ 28 ans en millisecondes). Croyez-moi, ça ne va pas déborder.
La seule chose qui peut apparaître est l'inexactitude. Mais un nombre à virgule flottante simple précision a une précision de 7 à 8 chiffres décimaux. Si vous l'utilisez pour mesurer les secondes, il est précis pendant environ 194 jours. Si vous mesurez des millisecondes, elle n’est précise que pour 4,5 heures. Cela dépend donc complètement de la précision dont vous avez besoin et vous devrez peut-être trouver d'autres moyens si vous devez être précis à la milliseconde près (ce que vous n'avez probablement pas).
la source
De combien de précision votre jeu a-t-il besoin?
Un float de 32 bits a une précision de 24 bits. En d'autres termes, à l'instant t, la précision est de ± 2 -23 × t. (Ce n'est pas tout à fait correct, mais c'est proche, et les détails exacts ne sont pas très intéressants.)
Si vous avez besoin d'une précision de 1 ms, après 1 ms ÷ 2 -23 = 8400 s = 2h 20m, un float de 32 bits n'est plus acceptable. Une précision de 1 ms n'est pas nécessaire pour la plupart des jeux, mais elle est considérée comme nécessaire pour les applications musicales.
Si votre jeu fonctionne sur un moniteur de 144 Hz et que vous souhaitez des graphiques précis, alors après 1 1 144 Hz 2 -23 = 58000 s = 16h, un float 32 bits n'est plus acceptable. 16h, c'est long de faire tourner une partie, mais ce n'est pas inconcevable. Je parie qu'un pourcentage important d'entre nous avons couru un match pendant 16 heures en un seul passage - même si nous avons laissé le match en cours d'exécution et avons obtenu un peu de sommeil. À ce stade, les animations et les mises à jour physiques seraient réduites à moins de 144Hz.
Si celle-ci
Time.deltaTime
est calculée à partir d'une horloge de précision supérieure, vous pouvez l'utiliser et obtenir une précision optimale. Je ne sais pas si c'est vrai ou pas.Note latérale
Les jeux et autres programmes sur Windows utilisent souvent
GetTickCount()
pour déterminer l'heure. Puisqu'il utilise un entier 32 bits pour compter les millisecondes, il tourne autour de tous les 50 jours environ, si vous laissez votre ordinateur trop longtemps. Je soupçonne que beaucoup de jeux se bloqueraient, se bloqueraient ou se conduiraient de manière bizarre si vous les jouiez à la marque des 50 jours.Les entiers, comme Windows
GetTickCount()
, risquent de déborder, alors que les flottants, comme ceux de UnityTime.time
, risquent de perdre de la précision.la source
Les autres réponses ne font que spéculer, alors j’ai écrit un simple projet Unity et l’a laissé fonctionner pendant un moment. Après quelques heures, voici le résultat:
UnityEngine.Time.time
perd de la précision assez rapidement. Comme prévu, après 4 heures de jeu, les valeurs sautent de 1 milliseconde et l’imprécision augmente par la suite.UnityEngine.Time.deltaTime
conserve sa précision initiale inférieure à la milliseconde même après que Unity a fonctionné pendant des heures. Ainsi, il est pratiquement garanti que le résultatdeltaTime
provient d'un compteur haute résolution dépendant de la plate-forme (qui déborde généralement après 10 à 1000 ans). Il reste un petit risque quideltaTime
perdra encore de la précision sur certaines plates-formes.L’inexactitude de Time est un problème pour tout ce qui en dépend
UnityEngine.Time.time
. Un exemple spécifique est la rotation (par exemple d’un moulin à vent), qui est généralement basée surUnityEngine.Mathf.Sin(UnityEngine.Time.time*rotationSpeed)
. Un problème encore plus important est celui_Time
qui est explicitement utilisé pour les animations par les shaders. Quelle doit être l'inexactitude avant de commencer à être perceptible? Une précision de 20-30 ms (2 jours) devrait être le point où les personnes qui sont au courant du problème et qui portent une attention particulière le remarqueront. À 50-100 ms (5-10 jours), les personnes sensibles qui ne connaissent pas le problème commenceront à le comprendre. A partir de 200-300 ms (20-30 jours), le problème sera évident.Jusqu'à présent , je ne l' ai pas testé l'exactitude des
_SinTime
,_CosTime
etUnity_DeltaTime
, donc je ne peux pas commenter ces.C'est le script que j'ai utilisé pour tester. Il est associé à un
UI.Text
élément, les paramètres de lecteur du projet permettent au projet de s'exécuter en arrière-plan et VSync dans les paramètres de qualité est défini sur Toutes les secondes vide.Si vous vous interrogez sur la
0.033203
valeur, je suis à peu près certaine que c'est en0.033203125
fait une représentation binaire à virgule flottante00111101000010000000000000000000
. Notez les nombreux0
s dans la mantisse.Solutions de contournement
La plupart des genres n'ont pas besoin d'une solution de contournement. La plupart des joueurs ne joueront même pas un jeu pendant 100 heures au total. Investir de l'argent pour résoudre un problème que les gens ne remarqueront donc qu'après quelques jours hypothétiques de temps de jeu continu est économiquement non viable. Malheureusement, je ne parviens pas à trouver une solution de contournement universelle simple qui résout le problème dans son ensemble sans entraîner des inconvénients importants.
la source