Le débugguage

  1. Introduction
  2. Lire le fichier log
  3. Débugguer
  4. Débugguer en traquant le bug

Créé le 09/11/2002
Dernière mise à jour le 09/11/2003

1) Introduction

Dans les jeux Unreal®, les bugs sont écrient dans un fichier *.log, ce fichier log porte le même nom que l'éxécutable du jeu en question (exemple: UnrealTournament.log, UT2003.log).
Pas trés important quand on débute l'UnrealScript avec des petits codes, mais un ou plusieurs bug(s) en passe rapide de code comme dans la function Tick() ou dans un passage de la HUD peut énormément buggé.
Une grosse accumulation de bugs peut faire grossir le fichier log jusqu'a plusieurs mo, et même faire planté le jeu!
Donc il faut débugguer son code dés le début, c'est à dire qu'a chaque test du code (aprés le rebuild (compilation) du package), si on trouve un bug, mieux vaut le supprimer aussitôt sans continué le code proprement dit, car quand il y en a plusieurs dizaines voir plus, ca devient plus compliqué et plus long à débugguer.

Top

2) Lire le fichier log

Déja il est nécessaire de comprendre le fichier log pour debbuguer.
On reconnais le type du message par le mot clef qui la commence (ex: Init, Log etc...).
Les bugs commencent par ScriptWarning pour la première génération du moteur (ex: UT) et juste par Warning dans la seconde (ex: UT2003), mais dans ce dernier il se peut que ce soit pas toujours un bug du a vôtre code mais parfois par quelque petites erreurs du jeu, qui sont en principe pas vraiment importantes, ne pas en tenir compte donc.

Quasiment tous les bugs sont des Accessed None, il y en a d'autre mais le log précisera plus en temps voulu.
Comme par exemple lorsqu'on utilise une variable d'une chaîne de variable qui dépasse la longueur de la chaîne déclarée. (voir ce tutorial pour comprendre de quelle type de variable je parle)

Le moteur veut dire par Accessed None qu'on s'est servi d'une variable de type Actor-Référence, qui faisait référence a aucun acteur.
Une fois qu'on a vraiment compris ce qu'il a voulu dire, c'est trés facile de corrigé l'erreur, ca serra expliqué dans le chapitre suivant.

Il se peut que ce soit pas exactement ca, mais concentrons nous dans ce qu'il y a entre les parenthèses et le type de bug (qui est écrit a la fin) pour comprendre le principe.
Les quatre **** représente une valeur héxadicimale, donc si c'est toujours la même valeur, il s'agit du même bug.

Exemple d'un bug dans une function:

Warning: MaClasse Package.MaClasseSupérieure.MaClasse (Function MonPackage.MaClasse.MaFonction:****) Accessed None

Exemple d'un bug dans un état:

Warning: MaClasse Package.MaClasseSupérieure.MaClasse (State MonPackage.MaClasse.MonEtat:****) Accessed None

Exemple d'un bug d'une function dans un état:

Warning: MaClasse Package.MaClasseSupérieure.MaClasse (Function MonPackage.MaClasse.MonEtat.MaFonction:****) Accessed None

Top

3) Débugguer

Maintenant qu'on sais a peu prés où est le bug voici quelques exemples:

Exemple si c'est pas sur que la variable est une référence:

var MyActor A;


function PostBeginPlay()
{
    Super.PostBeginPlay();

    A = Spawn(class'MyActor');
    Test();
}


function Test()
{
    if(A != None) // on vérifie que l'acteur existe bien
    {
        // mon code
    }
}

L'exemple le plus facile, si on doit utiliser A, comme une de ses functions, exemple: A.MyFunction(); et si a ce moment A n'existe pas, il y aurra forcément un Accessed None, mais pas dans l'exemple car on vérifie dabord que A (sa référence en fait) existe.
Si au contraire c'est sur que A réfère l'acteur, alors c'est pas nécessaire de vérifier A réfère un acteur.
Il faut savoir que si la réfèrence est détruite, la variable n'aurra plus de référence, est donc A redevient égal a None.
Mais si on détruit sa référence manuellement, exemple: A.Destroy(); et qu'on veut ré-utilisé la variable par la suite, mieux vaut mettre juste aprés: A = None;

Exemple pour vérifié si on a eu raison d'être sur:

...
function Test()
{
    if(A != None) // on vérifie que l'acteur existe bien
    {
        // mon code
    }
    else Log("Mon référence de la variable A n'existe pas!");
}

S'il se trouve qu'on c'était trompé, un message serra écrit dans le log.
Sachant que les message écrit dans le log de cette façon commence par ScriptLog.

Exemple pour être sur que l'acteur est bien apparu:

...
function PostBeginPlay()
{
    Super.PostBeginPlay();

    A = Spawn(class'MyActor');
    if(A != None) Test();
    else Log("Mon acteur n'est pas apparu car A n'a pas de référence");
}
...

Ici on vérifi si déja l'acteur a bien été spawné, en principe oui, mais dans certain cas, suivant la collision de l'acteur est l'endroit du spawn, si c'est hors de la map l'acteur ne serra pas spawné.
Ou tout simplement si un mutator empêche ce type d'acteur d'apparaîttre.

Top

4) Débugguer en traquant le bug

Si vous ne comprennez pas où est le bug ou si vous ne le voyez vraiment pas (c'est un peu la même chose en fait), ce qui peut arriver a n'importe qui, surtout quand le log a repérer le bug dans une function ou un état de plusieurs centaines de lignes.
On va se servir de la function Log() pour mieux repérer l'emplacement du bug.

function Test()
{
    Log("Test():1");
    // mon code
    Log("Test():2");
    // mon code
    Log("Test():3");
}

Donc si par exemple l'Accessed None est écris entre les messages 2 et 3, c'est sur qu'il y est, et non pas entre les messages 1 et 2.
Si sa suffit pas et qu'on trouve toujours pas, on refait pareil entre les messages 2 et 3, etc... jusqu'a refermé la tenaille sur le bug!
Pour que sa saute plus vite aux yeux dans le log, mettre plutot un message plus visible du type:

Log("================ Test():2 ================");

Note:
Une fois le debugging acqui, vous aurrez fait un petit pas de plus en programmation d'UnrealScript.

Top