Cette page décrit les problèmes de performance courants et les meilleures pratiques pour les atténuer.
Calcul du script
Les opérations coûteuses dans le code Luau prennent plus de temps à traiter et peuvent donc avoir un impact sur la fréquence des cadres.À moins qu'il ne soit exécuté en parallèle, le code Luau s'exécute en toute synchronie et bloque le thread principal jusqu'à ce qu'il rencontre une fonction qui fournit le thread.
Problèmes courants
Opérations intensives sur les structures de table - Les opérations complexes telles que la sérialisation, la désérialisation et le clonage profond entraînent un coût de performance élevé, notamment sur de grandes structures de table.Ceci est particulièrement vrai si ces opérations sont récursives ou impliquent d'itérer sur de très grandes structures de données.
Événements de haute fréquence - Attacher des opérations coûteuses à des événements basés sur le cadre de RunService sans limiter la fréquence signifie que ces opérations se répètent à chaque cadre, ce qui entraîne souvent une augmentation inutile du temps de calcul.Ces événements comprennent :
Atténuation
- Invokez du code sur RunService les événements de manière parcimonieuse, en limitant son utilisation aux cas où l'invocation fréquente est essentielle (par exemple, la mise à jour de la caméra).Vous pouvez exécuter la plupart du code restant dans d'autres événements ou moins souvent dans une boucle.
- Diviser les tâches importantes ou coûteuses en utilisant task.wait() pour répartir le travail sur plusieurs cadres.
- Identifier et optimiser les opérations inutilement coûteuses et utiliser le multithreading pour les tâches coûteuses en termes de calcul qui n'ont pas besoin d'accéder au modèle de données.
- Certains scripts côté serveur peuvent bénéficier de génération de code natif, un simple drapeau qui compile un script en code machine plutôt que en bytecode.
Scopes de microprofilage
Portée | Calcul associé |
Exécuter le service.PreRender | Code d'exécution lors de l'événement PreRender |
RunService.Présimulation | Code d'exécution sur l'événement Stepped |
Exécuter le service.PostSimulation | Code d'exécution sur événement Heartbeat |
Exécution du service.Cœur battant | Code d'exécution sur événement Heartbeat |
Pour plus d'informations sur la débogaison des scripts à l'aide du MicroProfiler, voir la bibliothèque debug, qui inclut des fonctions pour marquer du code spécifique et augmenter encore plus la spécificité, telles que debug.profilebegin et debug.profileend.De nombreuses méthodes de l'API Roblox appelées par des scripts ont également leurs propres balises MicroProfiler associées qui peuvent fournir un signal utile.
Utilisation de la mémoire du script
Les fuites de mémoire peuvent se produire lorsque vous écrivez des scripts qui consomment de la mémoire que le collecteur de déchets ne peut pas libérer correctement lorsqu'il n'est plus utilisé.Les fuites sont spécifiquement persistantes sur le serveur, car elles peuvent rester en ligne de manière continue pendant de nombreux jours, alors qu'une session client est beaucoup plus courte.
Les valeurs de mémoire suivantes dans la console de développeur peuvent indiquer un problème qui nécessite une enquête plus approfondie :
- LuaHeap - Une consommation élevée ou croissante suggère une fuite de mémoire.
- Nombre d'instances - Un nombre croissant de manière cohérente d'instances suggère que des références à certaines instances de votre code ne sont pas collectées en masse.
- Mémoire de script de placement - Fournit un script par répartition du volume de mémoire d'un script.
Problèmes courants
Quitter les connexions connectées - Le moteur n'élimine jamais les événements liés à une instance et toutes les valeurs référencées à l'intérieur du rappel connectéLes connexions actives d'événements et de code à l'intérieur des instances connectées, des fonctions connectées et des valeurs référencées sont donc hors de portée du collecteur de mémoire de garbage, même après que les événements soient déclenchés.
Bien que les événements soient déconnectés lorsque l'instance à laquelle ils appartiennent est détruite, une erreur commune est de supposer que cela s'applique aux objets Player .Après qu'un utilisateur ait quitté une expérience, le moteur ne détruit pas automatiquement son objet représentatif Player et son modèle de caractère, de sorte que les connexions à l'objet Player et aux instances sous le modèle de personnage, telles que Player.CharacterAdded, consomment toujours de la mémoire si vous ne les déconnectez pas dans vos scriptsCela peut entraîner des fuites de mémoire très importantes au fil du temps sur le serveur puisque des centaines d'utilisateurs rejoignent et quittent l'expérience.
Tabelles - Insérer des objets dans des tables mais ne pas les supprimer lorsqu'ils ne sont plus nécessaires provoque une consommation de mémoire inutile, notamment pour les tables qui suivent les données de l'utilisateur lorsqu'elles se joignent.Par exemple, l'exemple de code suivant crée une table qui ajoute des informations d'utilisateur à chaque fois qu'un utilisateur se joint :
Exemplelocal playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- quelques informationsend)Si vous ne supprimez pas ces entrées lorsqu'elles ne sont plus nécessaires, la table continue de croître en taille et consomme plus de mémoire à mesure que plus d'utilisateurs rejoignent la session.Tout code qui itère sur cette table devient également plus coûant en termes de calcul à mesure que la table augmente en taille.
Atténuation
Pour nettoyer toutes les valeurs utilisées pour empêcher les fuites de mémoire :
Désactivez toutes les connexions - Passez en revue votre base de code pour vous assurer que chaque connexion est nettoyée via l'une des voies suivantes :
- Déconnexion manuelle en utilisant la fonction Disconnect().
- Détruire l'instance à laquelle appartient l'événement avec la fonction Destroy().
- Détruire l'objet script auquel la connexion remonte.
Supprimer les objets et les personnages du joueur après avoir quitté - Implémenter le code pour garantir que les connexions ne persistent pas après le départ d'un utilisateur, comme dans l'exemple suivant :
ExemplePlayers.PlayerAdded:Connect(function(player)player.CharacterRemoving:Connect(function(character)task.defer(character.Destroy, character)end)end)Players.PlayerRemoving:Connect(function(player)task.defer(player.Destroy, player)end)
Calcul physique
La simulation physique excessive peut être une cause majeure de l'augmentation du temps de calcul par cadre sur le serveur et le client.
Problèmes courants
Fréquence de passe physique excessive - Par défaut, le comportement de passe est en mode adaptatif, où les pas de physique à 60 Hz, 120 Hz ou 240 Hz dépendent de la complexité du mécanisme physique.
Un mode fixe avec une précision améliorée de la physique est également disponible, qui force toutes les assemblages de physique à marcher à 240 Hz (quatre fois par cadre).Cela entraîne une augmentation significative de la computation à chaque cadre.
Nombre excessif de complexité des objets simulés - Plus il y a d'assemblages 3D qui sont simulés, plus les calculs physiques prennent de temps au fil du temps.Souvent, les expériences auront des objets simulés qui n'ont pas besoin d'être ou auront des mécanismes qui ont plus de contraintes et de jointures qu'ils n'en ont besoin.
Détection de collision trop précise - Les parties de maillage ont une propriété CollisionFidelity pour détecter la collision qui offre une variété de modes avec différents niveaux d'impact de performance.Le mode de détection de collision précis pour les parties de maillage a le coût de performance le plus élevé et prend plus de temps à la machine pour calculer.
Atténuation
Ancrer les parties qui ne nécessitent pas de simulation - Ancrer toutes les parties qui ne doivent pas être guidées par la physique, telles que pour les NPC statiques.
Utiliser l'ajustement dynamique de la physique adaptative - L'ajustement dynamique de la physique ajuste la vitesse des calculs de physique pour les mécanismes de physique, ce qui permet de réduire la fréquence des mises à jour de physique dans certains cas.
Réduisez la complexité du mécanisme * Dans la mesure du possible, minimisez le nombre de contraintes physiques ou de jointures dans une assemblage.
- Réduisez la quantité d'auto-collision dans un mécanisme, comme en appliquant des limites ou des contraintes de non-collision aux membres de ragdoll pour les empêcher de se heurter les uns aux autres.
Réduire l'utilisation de la fidélité de collision précise pour les mailles * Pour les objets petits ou non interactifs où les utilisateurs remarqueraient rarement la différence, utilisez la fidélité de la boîte.
Pour les objets de taille petite à moyenne, utilisez la fidélité boîte ou coque, en fonction de la forme.
Pour les objets très grands et très complexes, construisez des collisions personnalisées en utilisant des parties invisibles lorsque cela est possible.
Pour les objets qui n'ont pas besoin de collisions, désactivez les collisions et utilisez la fidélité de la boîte ou du hull, puisque la géométrie de collision est toujours stockée dans la mémoire.
Vous pouvez rendre la géométrie de collision pour des fins de débogage dans Studio en activant la fidélité à la collision à partir du widget Options de visualisation dans le coin supérieur droit de la fenêtre 3D.
Alternativement, vous pouvez appliquer le filtre à l'explorateur qui montre un nombre de toutes les parties de maillage avec une fidélité précise et vous permet de les sélectionner facilement.
Pour une explication approfondie de la façon de choisir une option de fidélité à la collision qui équilibre vos exigences de précision et de performance, voir Définir les paramètres de physique et de rendu.
Scopes de microprofilage
Portée | Calcul associé |
physiqueStepped | Calculs physiques globaux |
étape mondiale | Étapes de physique discrète prises à chaque frame |
Usage de la mémoire physique
Le mouvement physique et la détection des collisions consomment de la mémoire.Les parties de maillage ont une propriété CollisionFidelity qui détermine l'approche utilisée pour évaluer les limites de collision du maillage.
Problème courant
Les modes de détection de collision par défaut et précis consomment significativement plus de mémoire que les deux autres modes avec des formes de collision de plus faible fidélité
Si vous voyez des niveaux élevés de consommation de mémoire sous PhysicsParts , vous devrez peut-être explorer la réduction de la fidélité à la collision des objets dans votre experience.
Comment atténuer
Pour réduire la mémoire utilisée pour la fidélité de collision :
- Pour les parties qui n'ont pas besoin de collisions, désactivez leurs collisions en définissant BasePart.CanCollide, BasePart.CanTouch et BasePart.CanQuery à false .
- Réduisez la fidélité des collisions en utilisant le paramètre CollisionFidelity.Box a le plus faible dépassement de mémoire, et Default et Precise sont généralement plus chers.
- Il est généralement sûr de définir la fidélité à la collision de n'importe quelle petite partie ancrée à Box.
- Pour des mailles très complexes de grande taille, vous pouvez vouloir construire votre propre maillage de collision à partir de plus petits objets avec une fidélité de collision en boîte.
Humanoïdes
Humanoid est une classe qui fournit une large gamme de fonctionnalités aux personnages joueurs et non joueurs (NPC).Bien que puissant, un Humanoid vient avec un coût de calcul important.
Problèmes courants
- Quitter tous les types d'état humanoïde sur les PNJ activés - Il y a un coût de performance à quitter certains HumanoidStateTypes activés.Désactivez tout ce qui n'est pas nécessaire pour vos PNJs.Par exemple, à moins que votre PNJ ne monte sur des échelles, il est sûr de désactiver l'état Climbing.
- Instantanéisation, modification et réapparition fréquente de modèles avec des humanoïdes * Cela peut être intense pour le moteur de traiter, notamment si ces modèles utilisent des vêtements en plusieurs couches .Cela peut aussi être particulièrement problématique dans les expériences où les avatars réapparaissent souvent.
- Dans le MicroProfiler , les balises de mise à jour longues updateInvalidatedFastClusters (plus de 4 ms) sont souvent un signal indiquant que l'instantiation/la modification de l'avatar déclenche des invalidations excessives.
- Utiliser des humanoïdes dans des cas où ils ne sont pas nécessaires - Les PNJ statiques qui ne se déplacent généralement pas ont pas besoin de la classe Humanoid.
- Jouer des animations sur un grand nombre de PNJ à partir du serveur - Les animations des PNJ qui s'exécutent sur le serveur doivent être simulées sur le serveur et répliquées au clientCela peut être un surcoût inutile.
Atténuation
- Jouer les animations NPC sur le client - Dans les expériences avec un grand nombre de NPC, envisagez de créer le Animator sur le client et d'exécuter les animations localement.Cela réduit la charge sur le serveur et la nécessité d'une réplication inutileIl rend également possibles des optimisations supplémentaires (comme ne jouer que des animations pour les PNJ qui sont près du personnage).
- Utiliser des alternatives performantes aux Humanoïdes - Les modèles de PNJ n'ont pas nécessairement besoin de contenir un objet humanoïde
- Pour les NPCs statiques, utilisez un simple AnimationController , car ils n'ont pas besoin de se déplacer mais ont juste besoin de jouer des animations.
- Pour déplacer les PNJ, envisagez de mettre en œuvre votre propre contrôleur de mouvement et d'utiliser un AnimationController pour les animations, en fonction de la complexité de vos PNJ
- Désactiver les états humanoïdes inutilisés - Utilisez Humanoid:SetStateEnabled() pour activer uniquement les états nécessaires pour chaque humanoïde.
- Modèles NPC de piscine avec réapparition fréquente - Au lieu de détruire entièrement un NPC, envoyez le NPC dans une piscine de NPC inactifs.De cette façon, lorsqu'un nouveau PNJ doit réapparaître, vous pouvez simplement réactiver l'un des PNJ du pool.Ce processus s'appelle le pooling, ce qui minimise le nombre de fois où les caractères doivent être instantanés.
- Ne générez des PNJ que lorsque les utilisateurs sont à proximité - Ne générez pas de PNJ lorsque les utilisateurs ne sont pas à portée, et éliminez-les lorsque les utilisateurs quittent leur portée.
- Évitez de faire des modifications à la hiérarchie des avatars après qu'elle ait été instantanée - Certaines modifications d'une hiérarchie d'avatar ont des implications de performance importantes.Certaines optimisations sont disponibles :
- Pour les animations procédurales personnalisées, ne mettez pas à jour les propriétés JointInstance.C0 et JointInstance.C1. Au lieu de cela, mettez à jour la propriété Motor6D.Transform.
- Si vous devez attacher n'importe quel objet BasePart à l'avatar, faites-le en dehors de la hiérarchie de l'avatar Model.
Scopes de microprofilage
Portée | Calcul associé |
pasHumanoïde | Contrôle et physique des humanoïdes |
animation d'étape | Animation d'humanoïde et d'animateur |
mettre à jour les groupes de réplication rapide invalidés | Associé à l'instantiation ou à la modification d'un avatar |
Rendu
Une partie importante du temps que le client dépense à chaque cadre est consacrée à la rendu de la scène dans le cadre actuel.Le serveur ne fait pas de rendu, donc cette section est exclusive au client.
Faire des appels Draw
Un appel de dessin est un ensemble d'instructions du moteur vers la GPU pour rendre quelque chose.Les appels de dessin ont un surcoût important.En général, plus il y a moins d'appels de dessin par cadre, moins de temps de calcul est dépensé pour rendre un cadre.
Vous pouvez voir combien d'appels de dessin se produisent actuellement avec l'élément Render Stats > Temps dans Studio.Vous pouvez afficher les statistiques de rendu dans le client en appuyant sur ShiftF2.
Plus il y a d'objets à dessiner dans votre scène dans un cadre donné, plus il y a d'appels de dessin faits à la GPU.Cependant, le moteur Roblox utilise un processus appelé instanciation pour faire collapsser des mailles identiques avec les mêmes caractéristiques de texture dans un seul appel de dessin.Plus précisément, plusieurs mailles avec le même MeshId sont gérées dans un seul appel de dessin lorsque :
- SurfaceAppearances sont identiques. TextureIDs sont identiques lorsque SurfaceAppearance n'existe pas.
- Les matériaux sont identiques lorsque SurfaceAppearance et MeshPart.TextureID n'existent pas tous les deux.
Autres problèmes courants
Densité excessive d'objets - Si un grand nombre d'objets sont concentrés avec une densité élevée, alors le rendu de cette partie de la scène nécessite plus d'appels de dessin.Si vous trouvez que votre fréquence de cadence baisse lorsque vous regardez une certaine partie de la carte, cela peut être un bon signal indiquant que la densité d'objets dans cette zone est trop élevée.
Les objets tels que les décalcomanies, les textures et les particules ne se regroupent pas bien et introduisent des appels de dessin supplémentairesPrêtez une attention supplémentaire à ces types d'objets dans une scène.En particulier, les modifications de propriété à ParticleEmitters peuvent avoir un impact dramatique sur les performances.
Opportunités d'instanciation manquées - Souvent, une scène inclura le même maillage dupliqué plusieurs fois, mais chaque copie du maillage aura des ID de ressources de maillage ou de texture différents.Cela empêche l'instanciation et peut entraîner des appels de dessin inutiles.
Une cause commune de ce problème est lorsqu'une scène entière est importée en même temps, plutôt que d'importer des ressources individuelles dans Roblox et de les dupliquer après l'importation pour assembler la scène.
Complexité excessive de l'objet - Bien que ce ne soit pas aussi important que le nombre d'appels de dessin, le nombre de triangles dans une scène influence la durée pendant laquelle une image est rendue.Les scènes avec un très grand nombre de mailles très complexes sont un problème commun, tout comme les scènes avec la propriété définie sur trop de mailles.
Lancement excessif d'ombres - La manipulation des ombres est un processus coûteux, et les cartes contenant un grand nombre et une densité d'objets lumineux qui lancent des ombres (ou un grand nombre et une densité de petites parties influencées par les ombres) sont susceptibles de présenter des problèmes de performance.
Surpuissance de transparence élevée - Placer des objets à transparence partielle les uns près des autres force l'engine à rendre les pixels superposés plusieurs fois, ce qui peut nuire aux performances.Pour plus d'informations sur l'identification et la résolution de ce problème, voir Supprimer les transparences superposées.
Atténuation
- Instancier des mailles identiques et réduire le nombre de mailles uniques - Si vous vous assurez que toutes les mailles identiques ont les mêmes identifiants de ressources sous-jacentes, le moteur peut les reconnaître et les rendre dans un seul appel de dessin.Assurez-vous de n'uploader chaque maillage qu'une seule fois dans une carte, puis de les dupliquer dans Studio pour réutilisation plutôt que d'importer de grandes cartes dans leur ensemble, ce qui pourrait faire en sorte que des maillages identiques aient des ID de contenu différents et soient reconnus comme des ressources uniques par le moteur.Les paquets sont un mécanisme utile pour la réutilisation d'objets
- Élagage - L'élagage décrit le processus d'élimination des appels de dessin pour les objets qui ne font pas partie du cadre rendu final.Par défaut, le moteur ignore les appels de dessin pour les objets en dehors du champ de vision de la caméra (élimination du frustum), mais ne saute pas les appels de dessin pour les objets occultés de la vue par d'autres objets (élimination de l'occlusion).Si votre scène a un grand nombre d'appels de dessin, envisagez d'implémenter votre propre triage supplémentaire en temps d'exécution dynamiquement pour chaque cadre, comme l'application des stratégies communes suivantes :
- Pour les environnements intérieurs, mettez en œuvre un système de salle ou de portail qui cache les objets non occupés actuellement par aucun utilisateur.
- Réduire la fidélité du rendu - Définir la fidélité du rendu sur Automatique ou Performance .Cela permet aux mailles de revenir à des alternatives moins complexes, ce qui peut réduire le nombre de polygones qui doivent être dessinés.
- Désactivation du lancer d'ombres sur les parties et les objets légers appropriés - La complexité des ombres dans une scène peut être réduite en désactivant sélectivement les propriétés de lancer d'ombres sur les objets légers et les parties.Cela peut être fait au moment de l'édition ou dynamiquement lors de l'exécution.Quelques exemples sont :
Utilisez la propriété BasePart.CastShadow pour désactiver le lancer d'ombres sur de petites parties où il est peu probable que les ombres soient visibles.Cela peut être particulièrement efficace lorsqu'il est appliqué uniquement aux parties situées loin de la caméra de l'utilisateur.
Désactivez les ombres sur les objets en mouvement lorsque cela est possible.
Désactivez Light.Shadows sur les instances légères où l'objet n'a pas besoin de lancer des ombres.
Limitez la portée et l'angle des instances de lumière.
Utilisez moins d'instances légères.
Scopes de microprofilage
Portée | Calcul associé |
Préparer et exécuter | Rendement global |
Exécuter/Scène/ computeLightingPerform | Mise à jour de la grille légère et des ombres |
LumièreGridCPU | Mises à jour de la grille de lumière Voxel |
Système de cartes d'ombre | Cartographie des ombres |
Exécuter/Scène/Vue de mise à jour | Préparation au rendu et aux mises à jour des particules |
Exécuter/Scène/Vue de rendu | Rendement et post-traitement |
Réseau et réplication
La mise en réseau et la réplication décrivent le processus par lequel les données sont envoyées entre le serveur et les clients connectés.Les informations sont envoyées entre le client et le serveur à chaque cadre, mais de plus grandes quantités d'informations nécessitent plus de temps de calcul.
Problèmes courants
Trafic réseau excessif - L'envoi d'une grande quantité de données via RemoteEvent ou RemoteFunction objets ou leur invocation très fréquemment peut entraîner une grande quantité de temps de CPU dépensé pour traiter les paquets entrants à chaque cadre.Les erreurs courantes incluent :
- Repliquer les données à chaque cadre qui n'a pas besoin d'être repliqué.
- Répliquer des données sur l'entrée de l'utilisateur sans mécanisme pour les limiter.
- Envoi de plus de données que ce qui est requis.Par exemple, envoyer l'ensemble de l'inventaire du joueur lorsqu'il achète un article plutôt que seulement les détails de l'article acheté.
Création ou suppression d'arbres d'instance complexes - Lorsqu'une modification est apportée au modèle de données sur le serveur, elle est répliquée aux clients connectés.Cela signifie que la création et la destruction de grandes hiérarchies d'instance comme les cartes peuvent être très intensives en réseau au moment de l'exécution.
Un coupable commun ici est les données d'animation complexes sauvegardées par les plugins d'éditeur d'animation dans les rigs.Si ces derniers ne sont pas supprimés avant la publication du jeu et que le modèle animé est cloné régulièrement, une grande quantité de données sera répliquée inutilement.
Service Tween côté serveur - Si TweenService est utilisé pour faire pivoter un serveur d'objets côté serveur, la propriété pivotée est répliquée à chaque client à chaque cadre.Non seulement cela provoque l'anxiété du préadolescent lorsque la latence des clients fluctue, mais cela provoque beaucoup de trafic réseau inutile.
Atténuation
Vous pouvez utiliser les tactiques suivantes pour réduire la réplication inutile :
- Évitez d'envoyer de grandes quantités de données à la fois via des événements à distance .Au lieu de cela, envoyez uniquement les données nécessaires à une fréquence inférieure.Par exemple, pour l'état d'un personnage, répliquer-le lorsqu'il change plutôt que chaque cadre.
- Rassemblez des arbres d'instance complexes comme des cartes et chargez-les en morceaux pour distribuer le travail de réplication de ces dans plusieurs cadres.
- Nettoyer les métadonnées d'animation , notamment le répertoire d'animation des racks, après avoir importé.
- Limiter la réplication inutile d'instances , notamment dans les cas où le serveur n'a pas besoin de connaître les instances crééesCela inclut:
- Des effets visuels tels qu'une explosion ou une attaque de sort magique.Le serveur n'a besoin de connaître que l'emplacement pour déterminer le résultat, tandis que les clients peuvent créer des visualisations localement.
- Modèles de vue d'élément en première personne.
- Objets intermédiaires sur le client plutôt que sur le serveur.
Scopes de microprofilage
Portée | Calcul associé |
Paquets de traitement | Traitement des paquets réseau entrants, tels que les invocations d'événements et les modifications de propriété |
Allouer la bande passante et exécuter les expéditeurs | Evénements sortants pertinents sur les serveurs |
Utilisation de la mémoire des ressources
Le mécanisme d'impact le plus élevé disponible pour les créateurs pour améliorer l'utilisation de la mémoire du client est d'activer le streaming d'instance.
Streaming d'instance
La diffusion en instance charge sélectivement des parties du modèle de données qui ne sont pas requises, ce qui peut entraîner une réduction considérable du temps de chargement et augmenter la capacité du client à empêcher les crashs lorsqu'il est sous pression de mémoire.
Si vous rencontrez des problèmes de mémoire et que vous avez désactivé le streaming d'instance, envisagez de mettre à jour votre expérience pour la soutenir, notamment si votre monde 3D est vaste.La diffusion en instance est basée sur la distance dans l'espace 3D, donc les mondes plus grands en bénéficient naturellement plus.
Si la diffusion en instance est activée, vous pouvez augmenter son agressivité. Par exemple, envisagez :
- Réduire l'utilisation de l'intégrité de diffusion persistante StreamingIntegrity .
- Réduction du rayon de diffusion .
Pour plus d'informations sur les options de diffusion et leurs avantages, voir Propriétés de diffusion.
Autres problèmes courants
- Duplication des ressources - Une erreur commune consiste à télécharger la même ressource plusieurs fois avec des ID de ressources différents.Cela peut entraîner le chargement du même contenu dans la mémoire plusieurs fois.
- Volume de ressources excessif - Même lorsque les ressources ne sont pas identiques, il y a des cas où des opportunités de réutiliser la même ressource et d'économiser de la mémoire sont manquées.
- Fichiers audio - Les fichiers audio peuvent être un contributeur surprenant à l'utilisation de la mémoire, notamment si vous les chargez tous dans le client en même temps au lieu de ne charger que ce dont vous avez besoin pour une partie de l'expérience.Pour les stratégies, voir temps de chargement.
- Textures de haute résolution - La consommation de mémoire graphique pour une texture n'est pas liée à la taille de la texture sur le disque, mais plutôt au nombre de pixels dans la texture.
- Par exemple, une texture de 1024x1024 pixels consomme quatre fois la mémoire graphique d'une texture 512x512.
- Les images téléchargées sur Roblox sont transcodées en un format fixe, il n'y a donc pas d'avantage mémoire à télécharger des images dans un modèle de couleur associé à moins de pixels par pixel.De même, la compression des images avant leur téléchargement ou l'élimination du canal alpha des images qui n'en ont pas besoin peut réduire la taille des images sur disque, mais ne s'améliore pas ou ne s'améliore que légèrement l'utilisation de la mémoire.Bien que le moteur ajuste automatiquement la résolution des textures sur certains appareils, l'étendue de la réduction dépend des caractéristiques de l'appareil, et une résolution de texture excessive peut toujours causer des problèmes.
- Vous pouvez identifier la consommation de mémoire graphique pour une texture donnée en étendant la catégorie Mémoire graphique dans la console de développeur .
Atténuation
- Ne téléchargez des ressources que une fois - Réutilisez le même identifiant de ressource à travers les objets et assurez-vous que les mêmes ressources, notamment les mailles et les images, ne sont pas téléchargées plusieurs fois séparément.
- Trouver et corriger les ressources en double - Recherchez des parties de maillage et des textures identiques qui sont téléchargées plusieurs fois avec des ID différents.
- Bien qu'il n'y ait pas d'API pour détecter la similitude des ressources automatiquement, vous pouvez collecter toutes les ID de ressources d'image dans votre lieu (manuellement ou avec un script), les télécharger et les comparer à l'aide d'outils de comparaison externes.
- Pour les parties de maillage, la meilleure stratégie consiste à prendre des identifiants de maillage uniques et à les organiser par taille pour identifier manuellement les duplicates.
- Au lieu d'utiliser des textures séparées pour différentes couleurs, téléchargez une seule texture et utilisez la propriété SurfaceAppearance.Color pour appliquer divers tons dessus.
- Importer des ressources séparément sur la carte - Au lieu d'importer une carte entière à la fois, importer et reconstruire des ressources sur la carte individuellement et les reconstruire.L'importeur 3D n'effectue aucune déduplication des mailles, donc si vous importez une grande carte avec de nombreuses tuiles séparées, chacune de ces tuiles serait importée comme une ressource séparée (même si elles sont en double).Cela peut entraîner des problèmes de performance et de mémoire en aval, car chaque maillage est traité comme individuel et prend de la mémoire et fait des appels de dessin.
- Limitez les pixels des images à pas plus que la quantité nécessaire À moins qu'une image ne prenne beaucoup d'espace physique sur l'écran, elle a généralement besoin de 512x512 pixels au maximum.La plupart des images mineures devraient être plus petites que 256x256 pixels.
- Utilisez des feuilles de découpe pour garantir un maximum de réutilisation de la texture dans les cartes 3D.Pour les étapes et les exemples sur la façon de créer des feuilles de découpe, voir Créer des feuilles de découpe.
Délais de chargement
De nombreuses expériences implémentent des écrans de chargement personnalisés et utilisent la méthode ContentProvider:PreloadAsync() pour demander des ressources afin que les images, les sons et les mailles soient téléchargés en arrière-plan.
L'avantage de cette approche est qu'elle vous permet de vous assurer que des parties importantes de votre expérience sont entièrement chargées sans pop-in.Cependant, une erreur commune consiste à surutiliser cette méthode pour précharger plus de ressources que ce qui est réellement nécessaire.
Un exemple de mauvaise pratique est de charger le entierWorkspace .Bien que cela puisse empêcher l'apparition de textures, cela augmente sensiblement le temps de chargement.
Au lieu de cela, utilisez uniquement ContentProvider:PreloadAsync() dans les situations nécessaires, qui incluent :
- Images sur l'écran de chargement.
- Les images importantes dans le menu de votre expérience, telles que les arrière-plans de boutons et les icônes.
- Ressources importantes dans la zone de départ ou de génération.
Si vous devez charger un grand nombre de ressources, nous vous recommandons d'inclure un bouton Sauter le chargement .