Différence entre la méthode de mise à jour et FixedUpdate dans Unity?

14

je commence à apprendre Unity3d et l'une des confusions que j'obtiens est la différence entre Update()et FixedUpdate().

Je suis le didacticiel de développement de jeux Lynda Unity 2D là-bas, l'instructeur utilise la Updateméthode, le joueur a le composant RigidBody2D et le collisionneur de boîtes, il utilise la Updateméthode pour traduire le joueur, mais quand je fais la même chose dans Updatele joueur ne bouge pas mais quand je le fais en elle FixedUpdate, tout fonctionne. Il donne un tutoriel à partir de Unity 4.3 et je prends le cours dans Unity 4.6.

Où dois-je utiliser Updateet FixedUpdate?

moine
la source

Réponses:

14

J'allais écrire ceci comme un commentaire, mais cela a fini par être assez long, donc je l'ai transformé en réponse.

Les réponses actuelles sont généralement correctes, mais quelques éléments mentionnés sont trompeurs / erronés.

En général, la plupart des tâches liées au jeu entrent Update.

Par exemple, vous ne voulez pas interroger l'entrée FixedUpdate(pas à cause des performances, mais parce que les appels ne fonctionneront tout simplement pas correctement). AI tombe dans le même bateau.

La physique mise à jour en continu est la seule tâche liée au gameplay FixedUpdateà utiliser. Appels non continus / ponctuels à des choses comme Physics.Raycast, ou même à faire Rigidbody.AddForcepartie Update. Ma mention Rigidbody.AddForceest apparemment contraire à ce que pourrait impliquer la documentation, mais la clé est continue vs non continue.

Une des principales raisons pour lesquelles seule la physique continue appartient FixedUpdateest la nature réelle de FixedUpdate. D'autres réponses ont mentionné comment FixedUpdate est appelé à un fixe interval, but that's slightly misleading. In reality, a script is passed a time in Time.deltaTime/ Time.fixedDeltaTime* qui ne correspond pas directement au temps réel entre les appels, mais plutôt au temps simulé entre les appels.

(* Time.deltaTimeet Time.fixedDeltaTimeont la même valeur lorsqu'ils sont appelés dans FixedUpdate[Unity est en mesure de dire si l'appel en Time.deltaTimecours a commencé pendant FixedUpdateet revient Time.fixedDeltaTime])

Naturellement, la même manière Updatene peut pas être appelée de manière constante en raison des performances variables, non plus FixedUpdate. La principale différence est que, chaque trame, si elle FixedUpdaten'a pas été appelée assez souvent pour faire la moyenne de l'intervalle correct entre les appels, elle est appelée plusieurs fois (ou n'est pas appelée, la moyenne est trop élevée). C'est ce à quoi se réfèrent les documents sur l'ordre d'exécution en disant que FixedUpdate peut être appelé plusieurs fois par image:

... FixedUpdate: FixedUpdate est souvent appelé plus fréquemment que Update. Il peut être appelé plusieurs fois par trame, si la fréquence d'images est faible et il peut ne pas être appelé du tout entre les trames si la fréquence d'images est élevée ...

Cela n'affecte pas la physique en raison de la nature du reste de l'ordre d'exécution et du moteur, mais à peu près tout ce que vous insérerez FixedUpdatesera affecté et entraînera des problèmes.

Par exemple, si vous mettez le traitement de l'IA à l'intérieur, FixedUpdateil n'y a aucune raison de supposer que l'IA ne sautera pas les mises à jour pour plusieurs images consécutives. De plus, chaque fois que `FixedUpdate prend du retard, votre IA se mettra à jour plusieurs fois dans une seule image avant que des choses comme la physique et l'entrée / le mouvement du joueur ne soient traitées, ce qui est à tout le moins un gaspillage de traitement, mais est également extrêmement susceptible de causer des problèmes pour rechercher les bogues et les comportements erratiques.

Si vous devez faire quelque chose à un intervalle fixe, utilisez d'autres méthodes fournies par Unity telles que Coroutineset InvokeRepeating.

Et une petite note sur Time.deltaTimeet quand l'utiliser:

La façon la plus simple de décrire l'effet de Time.deltaTime est de changer un nombre d'unité par image en unité par seconde . Par exemple, si vous avez un script avec quelque chose comme transform.Translate(Vector3.up * 5)dans Update, vous déplacez essentiellement la transformation à une vitesse de 5 mètres par image . Cela signifie que si le framerate est faible, le mouvement est plus lent, et si le framerate est élevé, le mouvement est plus rapide.

Si vous prenez ce même code et le changez en transform.Translate(Vector3.up * 5 * Time.deltaTime), l'objet est déplacé à une vitesse de 5 mètres par seconde . Cela signifie que peu importe le débit d'images, l'objet se déplacera de 5 mètres toutes les secondes (mais plus le débit d'images est lent, plus le mouvement de l'objet apparaît rapidement car il se déplace toujours de la même quantité toutes les X secondes)

En général, vous voulez que votre mouvement soit par seconde. De cette façon, quelle que soit la vitesse de l'ordinateur, votre physique / mouvement se comportera de la même manière et vous n'aurez pas de bugs étranges sur des appareils plus lents.

Et cela ne sert à rien de l'utiliser FixedUpdate. En raison de ce que j'ai mentionné ci-dessus, vous obtiendrez la même valeur à chaque appel (la valeur Fixed Update Timestep), et cela ne fera rien à vos valeurs. Le mouvement / physique défini dans FixedUpdateva déjà être en unités par seconde, donc vous n'en avez pas besoin.

Selali Adobor
la source
4

La Updatefonction est appelée chaque trame. Sa fréquence dépend de la vitesse à laquelle l'ordinateur est capable de restituer des images. Sur un ordinateur plus lent, Updateest appelé moins fréquemment que sur un ordinateur plus rapide. Si vous effectuez des calculs basés sur le temps, vous pouvez les normaliser à l'aide de Time.deltaTimece qui vous indique le temps écoulé depuis le dernier Updateappel (des mises en garde s'appliquent).
Vous utiliserez généralement Updatepour effectuer des tâches liées à l'affichage (par exemple, la mise à jour d'un élément d'interface utilisateur)

La FixedUpdatefonction est appelée à intervalles fixes. Quelle que soit la fréquence de rafraîchissement de l'image, FixedUpdateelle sera appelée 1/Time.fixedDeltaTimefois par
seconde.Vous utiliserez généralement FixedUpdatepour effectuer des tâches liées au gameplay (par exemple, la mise à jour de la physique)

3Doubloons
la source
Est-ce une alternative à la multiplication par Time.delta time? Y a-t-il une raison d'utiliser l'un ou l'autre?
Ben
@Ben, ils ont deux objectifs différents et vous devez utiliser la fonction correcte pour ce que vous faites.
o0 '.
@ Lohoris Désolé, je voulais dire qu'il y a une raison d'utiliser FixedUpdate sur Update et de multiplier les choses par Time.deltaTime pour les rendre indépendantes du cadre?
Ben
@Ben oui, précision. Dans un système avec un rendu lent,Update on l'appelle de moins en moins souvent, et votre simulation en souffrira beaucoup. Vous ne le remarquerez peut-être pas pendant que la simulation est simple, mais elle se brisera horriblement facilement lorsqu'elle ne l'est pas.
o0 '.
1
@Ben no: si vous voulez que votre simulation soit précise, vous devez faire de nombreuses petites étapes, pas d'énormes à chaque fois plus ou moins aléatoires. Et non, l'intérêt de FixedUpdate est qu'il est appelé autant de fois, sans poser de questions.
o0 '.
2

De: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate

Le pas de temps utilisé dans FixedUpdate n'est pas variable.

Si votre jeu commence à prendre du retard, quand il se rattrape, vous ne voulez pas> 10 secondes de physique en une seule mise à jour, donc cela se fait généralement dans FixedUpdate qui est appelé à intervalle fixe.

Par exemple:

Update(float elapsedSeconds)
{
  Position += Velocity * 34.23423; //Windows Update is self-important
}
FixedUpdate(float elapsedSeconds)
{
  Position += Velocity * 0.0166; //60fps
}

Où:

Update(34.23423)

==

FixedUpdate(10.0)
FixedUpdate(10.0)
FixedUpdate(10.0)
//4.23423 + 5.76577 game-seconds later...
FixedUpdate(10.0)
Jon
la source
Je l'ai mentionné dans ma réponse, mais FixedUpdaten'est pas appelé à un intervalle fixe. La nature réelle de FixedUpdateest de compresser plusieurs cycles de physique en une seule image si votre jeu commence à prendre du retard et de sauter des cycles s'il va trop vite pour que la moyenne corresponde au pas de mise à jour fixe. Unity n'est pas multi-thread, il n'y aurait donc aucun moyen de garantir les appels FixedUpdate à un intervalle fixe (que se passe-t-il lorsqu'une FixedUpdate prend trop de temps). Même si c'était le cas, ce serait probablement encore presque impossible.
Selali Adobor
La plupart des gens [Unity?] Ne savent pas que Render / Update / FixedUpdate sont tous invoqués à partir d'une seule méthode de rappel, j'ai donc conceptualisé. Merci pour votre effort!
Jon
2

Updateest appelé aussi vite que possible. La variable «Time.deltaTime» est définie sur la durée réelle écoulée depuis le dernier appel. Si le décalage ou quelque chose de similaire ralentit le jeu, Updateil ne sera toujours appelé qu'une fois le décalage terminé, avec une valeur élevée de deltaTime.

FixedUpdateest appelé à intervalles réguliers. Il ne sera jamais appelé plus souvent que le rapport spécifié dans 'Time.fixedDeltaTime'. Si le décalage ou quelque chose de similaire ralentit le jeu, FixedUpdatesera appelé plusieurs fois de suite pour permettre au jeu de rattraper son retard.Time.deltaTimeest égal à Time.fixedDeltaTimeavant l' FixedUpdateexécution, mais ce n'est qu'un fudge pour faciliter la migration du code entre les deux.

Généralement, Update doit être utilisé pour les comportements interpolables et FixedUpdatepour les comportements qui doivent être calculés étape par étape, ou qui dépendent de ceux qui le font, comme les mouvements basés sur la physique. Si vous écrivez tout type de boucle dans Updatele sens de for(time=0;time<=deltaTime;time+=someStep)...alors vous devriez probablement le faire dans FixedUpdate à la place.

Mark Green
la source