Débogage et journalisation
Comment trouver et corriger les problèmes de vos scripts : lire les logs et les erreurs, recharger votre code rapidement et inspecter vos interfaces.
Afficher dans la console
La classe statique Console affiche des messages dans la console (et dans les fichiers de log), avec différents niveaux :
Console.Log("Normal message") -- always shown
Console.Warn("Something looks wrong") -- orange, shows the stack trace
Console.Error("Something is broken") -- red, shows the stack trace
Console.Debug("Only shown with log level 2 or 3") -- hidden by default
Toutes acceptent le formatage avec les spécificateurs de string.format, inutile donc de concaténer les valeurs vous-même :
Console.Log("Player %s has %d health at %s", player:GetName(), character:GetHealth(), tostring(character:GetLocation()))
print(...) fonctionne aussi : il est redirigé vers Console.Log.
Pour afficher le contenu d'une table, utilisez NanosTable.Dump(my_table).
Niveaux de log
Par défaut, les messages Console.Debug et les logs internes détaillés sont masqués. Pour les voir :
- Serveur : mettez
log_level = 2(debug) ou3(verbose) dans la section[debug]du Config.toml, passez--log_level 2au démarrage du serveur, ou lancez la commande consolelog_level 2. - Client : changez le log level dans les paramètres du jeu, section Debug.
Où sont les logs ?
Tout ce qui s'affiche dans la console est aussi enregistré sur le disque :
| Côté | Location |
|---|---|
| Serveur | Dossier .logs/ à côté de l'exécutable du serveur. NanosWorldCore.log correspond à la dernière session, les plus anciennes sont conservées avec leur date dans le nom du fichier |
| Client | %LocalAppData%\NanosWorld\Saved\Logs\ |
Sur le client, vous pouvez aussi ouvrir la console en jeu avec son raccourci (modifiable dans les paramètres) pour voir les logs et lancer des commandes en jouant.
Lire les erreurs Lua
Quand un script plante, l'erreur s'affiche en rouge avec l'endroit où elle s'est produite (par ex. dans quel événement), suivie de la stack trace : la chaîne d'appels de fonctions qui a mené à l'erreur, avec le fichier et la ligne de chacun. La première ligne ([1]) indique où l'erreur s'est produite. Par exemple :
ERROR Lua Error on Class 'my-package' Event 'TakeDamage':
- [1] [my-package/Server/Index.lua]:24: attempt to call a nil value (global 'Sound')
- [2] [my-package/Server/Index.lua]:77: in function <[string "my-package/Server/Index.lua"]:69>
Cela signifie qu'à la ligne 24 de my-package/Server/Index.lua, dans un événement TakeDamage, le code a essayé d'appeler Sound(...), mais Sound n'existe pas à cet endroit. Ici, c'est parce que Sound est une classe uniquement côté client et que le code s'exécute sur le serveur !
Corrigez toujours la première erreur que vous voyez. Les erreurs suivantes en sont généralement la conséquence.
Erreurs courantes et leur signification habituelle
attempt to index a nil value
Une fonction a renvoyé
nilet vous avez utilisé le résultat, par ex.player:GetControlledCharacter()alors que le joueur ne contrôle rien, ouProp.GetByIndex(10)alors qu'il y a moins de Props. Vérifiez que la valeur n'est pasnilavant de l'utiliser
attempt to call a nil value (method 'X') ou (global 'X')
La méthode ou la classe n'existe pas, ou n'est pas disponible de ce côté (par ex. créer une classe client sur le serveur). Vérifiez son nom et son autorité dans la Scripting Reference
attempt to concatenate a boolean/nil value
Utilisation de
..avec quelque chose qui n'est ni une chaîne ni un nombre. Utiliseztostring(value)ou le formatageConsole.Log("%s", value)
attempt to perform arithmetic on a nil value
Une variable utilisée dans un calcul n'a jamais été définie, par ex. un
GetValuequi a renvoyénil. Passez une valeur par défaut :GetValue("score", 0)
Expected a class as parameter
Vous avez passé une chaîne à
IsA: utilisez la classe elle-même,entity:IsA(Weapon)
Invalid Channel!, Invalid Index!, etc.
Un paramètre sort de sa plage autorisée : vérifiez la description de la méthode dans la Scripting Reference
Recharger votre code
Inutile de redémarrer le serveur pour tester vos modifications. Dans la console du serveur, utilisez :
package reload my-package
Décharge puis recharge le Package, en détruisant les entités qu'il a créées (si
auto_cleanupest activé). Les joueurs reçoivent automatiquement les fichiers client mis à jour
package hotreload my-package
Recharge tous les fichiers mais conserve la mémoire Lua (variables globales) telle quelle |
package reload all
Recharge tous les Packages en redémarrant toute la machine virtuelle Lua |
Comme l'événement Load est redéclenché au rechargement, c'est une bonne pratique d'écrire votre Package pour qu'il fonctionne même rechargé alors que des joueurs sont déjà connectés. Par exemple, si vous créez des Characters pour les joueurs sur Player "Spawn", parcourez aussi les joueurs déjà connectés sur Package "Load" (voir le démarrage rapide).
Déboguer les WebUIs
Les WebUIs tournent dans un vrai navigateur Chromium : vous pouvez donc utiliser ses outils de développement pour inspecter le HTML, voir les erreurs JavaScript et déboguer votre code :
local my_ui = WebUI("My UI", "file://UI/index.html")
-- Opens the Chromium DevTools for this WebUI
my_ui:OpenDevTools()
Les messages JavaScript console.log s'affichent aussi dans la console du jeu, avec le type de log WebUI.
Déboguer le monde
- La classe statique Debug dessine des lignes, boîtes, sphères et textes dans le monde : idéal pour visualiser des positions, des directions et des traces. Les traces peuvent aussi se dessiner elles-mêmes avec
TraceMode.DrawDebug. - Pour voir comment les entités sont synchronisées et qui est leur Network Authority, activez Draw Network Debug dans les paramètres (Settings -> Debug). Voir Déboguer le réseau et la Network Authority.
-- Draws a red sphere for 10 seconds where a Character is
Debug.DrawSphere(my_character:GetLocation(), 50, 12, Color.RED, 10)
Problèmes de performance
Si votre serveur affiche des avertissements Server Tick too high! ou si le jeu ralentit, consultez le guide Profilage pour trouver quel code prend trop de temps.