Blog des développeurs | Chargez !

Aujourd'hui, dans notre série de blogs des développeurs dédiés à NXT, Mod Dunk nous explique les changements qu'il fallait réussir à implémenter pour obtenir une qualité de mouvement fluide avec le nouveau client de RuneScape.


RuneScape est un immense jeu rempli de personnages à rencontrer, de quêtes et de régions à explorer. Ces 15 ans de contenus pèsent lourd sur l'actuel client de jeu Java, et le nouveau client NXT vous apportera un moteur de jeu moderne capable de prendre efficacement en charge la taille de RuneScape, maintenant et à l'avenir.

Le chargement est fréquemment un problème lors du développement d'un jeu, particulièrement dans le cas des jeux en monde ouvert comme RuneScape. Comme le joueur peut choisir d'aller dans n'importe quelle direction et que la zone est trop grande pour être gardée en mémoire, le jeu doit pouvoir charger un immense nombre de ressources en douceur, et sans interrompre la fluidité de l'expérience de jeu.

Et là, je suis sûr que vous vous dites : « une petite seconde, mais il me semble bien que RuneScape marque des pauses le temps que le jeu charge. » Et oui, vous avez raison. En fait, la boîte de dialogue affichant le message « Chargement en cours... Veuillez patienter », et mettant le jeu en pause pendant vos déplacements en jeu, est sans doute une vision familière pour tous les joueurs de RuneScape.

Mais ce message ne sera plus nécessaire avec NXT, et voilà comment nous avons procédé :

Processus de « streaming »

L'univers de jeu de RuneScape est divisé en cases. Au fil de vos déplacements, les cases devant votre personnage sont chargées pendant que celles qui se trouvent derrière lui sont supprimées afin d'économiser de la mémoire. Pour ce faire, le client Java a besoin d'arrêter l'ensemble du jeu, et il le met donc en pause.

L'un des objectifs principaux de NXT était de faire en sorte que ce chargement se déroule en « arrière-plan », sans jamais interrompre votre expérience de jeu. La technique utilisée est appelée « streaming » ou « chargement asynchrone » car elle se produit en parallèle pendant que le jeu principal continue de tourner.

À cette fin, on encapsule chaque requête de chargement sous la forme d'un objet « tâche ». Et chaque tâche est envoyée à l'un de nos fils d'exécution. Ces fils traitent alors ces tâches par eux-mêmes, puis renvoient tout simplement le résultat une fois le traitement terminé.

Malheureusement, cela impliquait pour nous de réécrire toutes nos données concernant nos modèles 3D, animations, textures, systèmes de particules, objets du script... En gros, tout le jeu. Comme vous pouvez l'imaginez, c'était un travail d'envergure. Mais le jeu en vaut vraiment la chandelle puisque tous ces efforts nous permettent de vous offrir la possibilité de vous déplacer à travers le monde de RuneScape de manière plus fluide, ce qui serait autrement impossible avec le client Java !

Effets d'eau

Prêtez attention aux changements de lumière lors des déplacements d'une case de zone à l'autre.

Processus de « packing »

La capacité de charger un grand nombre de fragments de jeu rapidement est une condition essentielle pour permettre l'extension de la ligne d'horizon avec NXT.

Avec NXT, nos distances d'affichage maximum sont 4 fois supérieures à celles de Java, ce qui nécessite de charger environ 16 fois plus de modèles simultanément. Certes, nous avons vu que ce chargement se déroule en parallèle. Mais le nombre important de modèles à charger exige aussi d'augmenter la vitesse de chargement individuel de chaque élément.

Chaque chargement de modèle entraîne le traitement d'une grande quantité de données visant à calculer les paramètres nécessaires pour son rendu. Comme dans tout jeu vidéo, toutes les surfaces visibles des modèles 3D sont constitués de triangles. Les 3 angles, ou vertex, d'un triangle contiennent chacun des informations comme la normale à la surface, la couleur et les coordonnées de texture.

Avec le client Java, le code de chargement traite des algorithmes qui calculent ces valeurs, ce qui peut s'avérer très lent. Pour NXT, nous pré-programmons ces valeurs au cours d'une phase de « packing » externe afin qu'elles aient simplement à être lues directement au moment du chargement. Malgré l'augmentation de la taille des ressources à charger, ce processus qui permet d'accélérer énormément les temps de chargement nécessaires, reste notre approche préférée chaque fois que c'est possible.

De la même manière, nous avons établi un processus de « packing » externe pour la compression des données de textures, ce qui diminue la quantité d'informations à traiter au moment du chargement.

Distance visible avec Java Distance visible avec NXT

Ci-dessus : Distance visible avec Java. Ci-dessous : Distance visible avec NXT.

Préchargement

Avec le client Java, le simple fait d'accéder à l'écran de connexion nécessite un écran de chargement. Ce temps a été considérablement diminué avec NXT. Nous effectuons maintenant une bien plus grande partie du travail nécessaire au moment où le joueur se trouve sur l'écran d'accueil. Hormis l'affichage du menu, c'est un stade où l'ordinateur ne fait pas grand-chose. Nous avons donc le temps de procéder autant que possible au préchargement.

Et la tâche principale consiste à précharger l'environnement de jeu nécessaire. Si, par exemple, vous vous étiez déconnecté à Lumbridge, c'est la zone de Lumbridge que le client devra charger en parallèle au moment de votre connexion puisque c'est là que vous apparaîtrez à votre retour dans le monde du jeu.

C'est aussi à ce moment que nous procédons au préchargement du nuanceur. Les nuanceurs sont de petits programmes qui tournent sur la carte graphique et qui effectuent des calculs nécessaires au rendu visuel. Avec NXT, nous maintenons une liste de nuanceurs communément utilisés et nous nous assurons qu'ils sont disponibles avant que le jeu commence.

Niveau de détail des cases

Avec NXT, nous optimisons le chargement des cases lointaines en nous attachant uniquement à la construction et au rendu des éléments de décor les plus importants. Par exemple, on devrait toujours pouvoir voir de loin les murs d'un bâtiment, mais les détails intérieurs n'ont pas besoin d'être chargés tant que vous ne vous êtes pas assez approché pour pouvoir voir à l'intérieur. Ce système de « niveau de détails » est très efficace pour accélérer le chargement et le rendu visuel quand les distances d'affichage sont si étendues.

Armadyl's Tower

Les immenses éléments de décor, comme la Tour d'Armadyl, sont chargés lorsqu'ils apparaissent au loin, mais pas les éléments de détails comme l'herbe ou les fleurs qui se trouvent autour.

Permutation de nuanceurs

Le monde de RuneScape se constitue de différents objets, faits de divers matériaux. Chaque matériau peut utiliser une combinaison d'effets visuels, comme le mappage de l'environnement, le rendu de texture, des effets de lumières spectaculaires, la simulation de transparence, l'émission d'éclairs et bien plus encore.

Avec NXT, nous avons implémenté d'autres fonctionnalités, au niveau par exemple des animations, des effets de brouillard ou d'ombre. La possibilité d'activer ou de désactiver indépendamment chacune d'entre elles a généré plusieurs centaines, voire même plusieurs milliers de permutations de nuanceurs et de variantes. Nous avons, heureusement, réduit ce nombre à une centaine, et nous écrivons actuellement davantage de codes pour les réduire encore plus.

Pour parvenir à ce résultat, nous avons plusieurs manières de procéder :
  • Nous identifions les caractéristiques de nuanceurs produisant le plus de permutations, en utilisant un outil interne de résolution de bug.
  • Les caractéristiques très sollicitées et peu coûteuses à utiliser sont simplement rendues disponibles de manière permanente.
  • Les caractéristiques très sollicitées mais coûteuses à utiliser peuvent être activées ou désactivées à l'intérieur du programme du nuanceur lui-même.

L'un des gros problèmes des moteurs de jeu génériques comme Unreal ou Unity, c'est que l'utilisateur peut facilement créer différents matériaux nécessitant plusieurs milliers de permutations de nuanceurs, augmentant ainsi le temps nécessaire pour tous les charger. Comme NXT doit uniquement gérer un ensemble de données très spécifiques (quoique conséquent), nous pouvons optimiser nos rendus visuels et l'efficacité de notre code de nuanceurs pour générer moins de permutations.

Tout ce travail vise un objectif louable : nous voulons nous assurer que le client NXT peut améliorer grandement votre expérience visuel dans l'univers de RuneScape, tout en battant le client Java au niveau des temps de chargement.

Mod Dunk
Développeur de moteur graphique

Haut de la page