Le mythe du Tick dans Unreal Engine

Blueprint visual scripting, programmation nodale, tutoriels et astuces, introduction au langage Verse
Avatar de l’utilisateur
Poppy
Messages : 203
Inscription : 17 sept. 2022, 16:17





Lors de l'Unreal Fest 2024, Ari Arnbjornsson ingénieur senior chez Epic Games a donné une conférence sur le mythe des meilleures pratiques dans Unreal Engine.

Commençons par les Ticks. Les Ticks sont-ils vraiment si problématiques ? Vous avez probablement déjà entendu parler de Ticks et de leurs consommation. Mettons-les à l'épreuve et découvrons ce qu'il en est vraiment.



Vous n'utilisez pas le Tick ?

Tick est une fonction que n'importe quel objet peut implémenter pour faire tourner du code à chaque frame du jeu.





Parlons des Ticks

Une grande partie du code du jeu se déroule dans les Ticks, et les Ticks ne s'exécutent que sur le Game Thread, à un seul thread.

Tick est puissant :

- Les groupes de Ticks : Ils vous permettent de choisir à quelle frame l'objet tick, par exemple avant ou après que la physique ait été calculée. Je tiens à souligner le groupe de tick « DuringPhysics » que vous pouvez utiliser lorsque vous n'avez pas besoin de lire ou de définir des transformations, vous pouvez alors exécuter ce tick pendant qu'UE calcule sa physique.
- Les dépendances du Tick : Permet de faire en sorte qu'un acteur ne se déclenche qu'après que d'autres acteurs spécifiques se soient déclenchés en premier.
- Intervalle entre les ticks : Vous pouvez le modifier à tout moment pour n'importe quel acteur.
- Désactivation / Activation du Tick : Vous pouvez désactiver ou activer la fonction Tick d'un acteur à tout moment.

Le Tick a un léger surcoût de consommation à cause de ces fonctionnalités.



Tick a un léger surcoût

Le Tick a une certaine consommation, mais ce n'est que léger. Il n'est perceptible que lorsque vous avez beaucoup d'acteurs qui font des ticks. Les couts sont généralement négligeables par rapport au travail que vous effectuez pendant le Tick.



Combien ça consomme ? Mesurons-le !






Nous avons deux phases au cours desquelles les ticks apparaissent sur le profileur, la mise en file d'attente de tous les ticks et ensuite la consommation de chaque Tick individuellement. Dans l'image ci-dessus, nous comparons la consommation des ticks pour ces deux phases pour :
- Ticks du Blueprint dans l'éditeur (bleu foncé)
- Ticks Blueprint dans une version de développement packagée (bleu clair)
- Tics C++ dans l'éditeur (vert foncé)
- Tics C++ dans une version de développement packagée (vert clair)

Ces mesures sont effectuées en microsecondes (μs) sur mon ordinateur de travail équipé d'un threadripper cadencé à 2,69 GHz. Il y a 1000 microsecondes (μs) dans chaque milliseconde (ms), et il y a environ 16 millisecondes par image dans un jeu à 60fps. Nous avons donc 16 000 microsecondes (μs) au total par image.

En regardant cette image, vous vous dites peut-être : « Les tics de l'éditeur BP sont très lents ! Regardez la hauteur de cette barre ! »

Mais cette surcharge prend plus de sens une fois que nous la replaçons dans son contexte, plus précisément dans le contexte du temps que prend le code que nous exécutons au cours d'un Tick :



Cette image reprend la consommation du Tick de l'image précédente et le compare à quelques fonctions qui sont appelées pendant la fonction Tick du PlayerCharacter dans le projet Lyra.

Le CharacterMovementComponent prend 241,1 microsecondes (μs), et le PlayerController prend 125 μs supplémentaires. Le PlayerCharacter de Lyra appelle ces deux fonctions et d'autres encore au cours de chaque Tick. En comparaison, le Tick lui-même est à peine visible sur le graphique. J'ai en fait mesuré la consommation de ce Tick en proportion des fonctions qu'il appelle, il est en fait plus petit que le poids de l'emballage d'une barre de Mars en proportion de la barre de Mars elle-même.

Et pour ajouter plus de contexte, vous verrez que j'ai ajouté Rifle_SKM de Lyra ici aussi. Les fusils de Lyra ont en fait une petite animation de tir où le bout du canon bouge un tout petit peu quand on tire. Et cela prend 20,7 microsecondes (μs) ! Mais les gens s'insurgent quand même contre la consommation du Tick.



La consommation des Tick vides



Le pire est d'avoir une fonction Tick vide, c'est alors un overhead de 100%, il faut donc s'assurer de ne pas avoir de Ticks vides sur les acteurs.

Pour les Blueprints, c'est ce à quoi vous devez faire attention :



Si le Blueprint n'a pas de fonction Tick, il ne se déclenchera pas.

Si le Blueprint a la fonction de Tick fantôme qu'Unreal crée par défaut sur les nouveaux acteurs, il ne se déclenchera toujours pas.

Cependant, si vous connectez le fil de ce Tick fantôme et que vous décidez ensuite de l'enlever, la fonction Tick réelle reste. Une fonction Tick vide comme celle-ci comptera comme un Tick et causera la surconsommation mentionné ci-dessus.



De mauvais conseils avec de bonnes intentions


Image Victor Lahlou

Il peut arriver qu'un nouveau développeur mette beaucoup d'appels de fonctions dans la fonction Tick d'un Blueprint et qu'il se rende compte que les performances du jeu en sont affectées de manière drastique. Et quelqu'un qui est passé par là vous dira peut-être « n'utilisez pas la fonction Tick ! ».


Image Victor Lahlou

Mais cela peut avoir pour effet que le développeur pense que la fonction Tick est en quelque sorte mauvaise. Qu'il ne faut jamais, au grand jamais, l'utiliser dans quelque situation que ce soit.



Le problème des tics

Les gens disent que « les Ticks ralentissent votre jeu ! ». Mais c'est en fait le fait de « faire un tas de travail par image et par acteur » qui est lent.

Peu importe que vous utilisiez des Ticks, des Timelines, des Timers, des Anim Notifies, etc. La consommation n'est généralement pas le problème, c'est le travail qui l'est. Si vous devez faire quelque chose à chaque image pour un acteur, utilisez simplement le Tick ! Si vous créez une Timeline pour faire quelque chose à chaque image pour « éviter d'avoir à utiliser le Tick », alors vous n'avez pas compris.

Vous avez toujours besoin de ticks dans vos projets. Par exemple, nous avons environ 80 ticks en moyenne pour une session client Fortnite qui fonctionne sur un grand nombre d'appareils différents comme Switch et Android. Et le serveur de Fortnite aura une moyenne d'environ 700 ticks par image pour une session.

Mais essayez de ne pas faire trop de travail à chaque image, quelle que soit la méthode que vous utilisez. Cela peut être dû au fait d'avoir moins d'acteurs qui font des ticks et/ou de faire moins de travail par ticks.

De plus, ne tiquez pas les acteurs qui n'ont rien à faire là. Si vous faites un jeu à balles avec un millier de balles, ne faites pas en sorte que chaque balle soit son propre acteur avec sa propre fonction Tick. 1000 acteurs ticking représenteront 3,5 millisecondes de pure surcharge. Au lieu d'un ticking agrégé, ayez un BP_BulletManager qui calcule les positions des balles et met les graphiques des balles dans un composant Instance Static Mesh.

Si vous avez beaucoup de données à traiter, vous pouvez également utiliser le système de masse. Cela peut être compliqué, donc ne pensez pas que c'est une solution facile à mettre en place. Sinon, essayez d'en faire moins à chaque image en ne cochant pas les objets hors de l'écran ou en cochant moins souvent les acteurs qui sont loin.

Je pense qu'un meilleur conseil serait ce que KaosSpectrum du serveur Discord d'Unreal Source a dit : « Utilisez les Ticks, n'abusez pas des Ticks ».



« N'utilisez pas les Ticks », vrai ou faux ?

C'est évidement FAUX ! Vous pouvez utiliser la fonction Tick mais avec modération ;)

Notez cependant que qu'il ne faut pas faire trop de travail en Ticks et qu'il ne faut pas avoir une quantité déraisonnable de Ticks en cours d'exécution. Vous saurez quand vous faites trop de travail ou quand le nombre de Ticks est déraisonnable grâce au PROFILAGE !

Avatar de l’utilisateur
Bender
Site Admin
Messages : 385
Inscription : 15 sept. 2022, 13:14

Salut Poppy, ils sont super tes posts sur les mythes des blueprints !! Bravo ;)
Répondre