Étant donné que de nombreux utilisateurs sont confrontés à l' NullReferenceException: Object reference not set to an instance of an object
erreur dans Unity, j'ai pensé que ce serait une bonne idée de rassembler à partir de plusieurs sources des explications et des moyens de corriger cette erreur.
Symptômes
Je reçois l'erreur ci-dessous qui apparaît dans ma console, qu'est-ce que cela signifie et comment puis-je la corriger?
NullReferenceException: référence d'objet non définie sur une instance d'un objet
unity
exceptions
Hellium
la source
la source
Réponses:
Type de valeur vs type de référence
Dans de nombreux langages de programmation, les variables ont ce qu'on appelle un "type de données". Les deux principaux types de données sont les types de valeur (int, float, bool, char, struct, ...) et le type de référence (instance de classes). Alors que les types de valeurs contiennent la valeur elle - même , les références contiennent une adresse mémoire pointant vers une partie de la mémoire allouée pour contenir un ensemble de valeurs (similaire à C / C ++).
Par exemple,
Vector3
est un type de valeur (une structure contenant les coordonnées et certaines fonctions) tandis que les composants attachés à votre GameObject (y compris vos scripts personnalisés héritant deMonoBehaviour
) sont de type référence.Quand puis-je avoir une NullReferenceException?
NullReferenceException
sont levées lorsque vous essayez d'accéder à une variable de référence qui ne fait référence à aucun objet, elle est donc nulle (l'adresse mémoire pointe vers 0).Quelques lieux communs a
NullReferenceException
seront soulevés:Manipulation d'un GameObject / Component qui n'a pas été spécifié dans l'inspecteur
Récupérer un composant qui n'est pas attaché au GameObject puis essayer de le manipuler:
Accéder à un GameObject qui n'existe pas:
Note: Attention,
GameObject.Find
,GameObject.FindWithTag
,GameObject.FindObjectOfType
retour seulement GameObjects qui sont activés dans la hiérarchie lorsque la fonction est appelée.Essayer d'utiliser le résultat d'un getter qui revient
null
:Accéder à un élément d'un tableau non initialisé
Moins commun, mais ennuyeux si vous ne le savez pas sur les délégués C #:
Comment réparer ?
Si vous avez compris les paragraphes précédents, vous savez comment corriger l'erreur: assurez-vous que votre variable référence (pointe vers) une instance d'une classe (ou contient au moins une fonction pour les délégués).
Plus facile à dire qu'à faire? Oui en effet. Voici quelques conseils pour éviter et identifier le problème.
La manière "sale": La méthode try & catch:
La voie "plus propre" (IMHO): Le chèque
Lorsque vous faites face à une erreur que vous ne pouvez pas résoudre, c'est toujours une bonne idée de trouver la cause du problème. Si vous êtes "paresseux" (ou si le problème peut être résolu facilement), utilisez
Debug.Log
pour afficher sur la console des informations qui vous aideront à identifier la cause du problème. Une manière plus complexe consiste à utiliser les points d'arrêt et le débogueur de votre IDE.L'utilisation
Debug.Log
est très utile pour déterminer quelle fonction est appelée en premier par exemple. Surtout si vous avez une fonction chargée d'initialiser les champs. Mais n'oubliez pas de les supprimerDebug.Log
pour éviter d'encombrer votre console (et pour des raisons de performances).Un autre conseil, n'hésitez pas à "couper" vos appels de fonction et à les ajouter
Debug.Log
pour faire quelques vérifications.Au lieu de :
Procédez ainsi pour vérifier si toutes les références sont définies:
Encore mieux :
Sources:
la source
try/catch
. L'erreur vous en dit long sur le problème que vous rencontrez, et avant que les débutants commencent à mettre des vérifications nulles partout, votre problème principal est dans l'inspecteur car vous oubliez de référencer un objet (faites glisser l'objet sur le script). J'ai vu beaucoup de code avectry/catch
et des contrôles nuls dans des endroits où c'est totalement inutile. Déboguer et travailler avec un code comme celui-ci est «une douleur dans le **». Les débutants se renseignent sur les cas d'utilisation de ces vérifications et les utilisent ensuite.else
. Avoir unNullReferenceException
n'est pas toujours explicite toutNo Rigidbody component attached to the gameObject
en expliquant directement ce qui ne va pas. Je suis d'accord que le simple fait d'avoir leif( obj != null )
message sans "cache" le problème, et vous pouvez avoir un projet de travail mais ne pas faire ce que vous attendez sans savoir pourquoi.Bien que nous puissions facilement vérifier simplement que nous n'essayons pas d'accéder à une référence nulle, ce n'est pas toujours une solution appropriée. Plusieurs fois, dans la programmation Unity, notre problème peut provenir du fait que la référence ne doit pas être nulle. Dans certaines situations, le simple fait d'ignorer les références nulles peut briser notre code.
Par exemple, il peut s'agir d'une référence à notre contrôleur d'entrée. Il est formidable que le jeu ne plante pas en raison de l'exception de référence nulle, mais nous devons comprendre pourquoi il n'y a pas de contrôleur d'entrée et résoudre ce problème. Sans cela, nous avons un jeu qui ne peut pas planter, mais ne peut pas non plus prendre de données.
Ci-dessous, je vais énumérer les raisons et les solutions possibles, au fur et à mesure que je les rencontre dans d'autres questions.
Essayez-vous d'accéder à une classe "manager"?
Si vous essayez d'accéder à une classe qui agit en tant que «gestionnaire» (c'est-à-dire une classe qui ne devrait avoir qu'une seule instance en cours d'exécution à la fois), vous feriez mieux d'utiliser l'approche Singleton . Une classe Singleton est idéalement accessible de n'importe où, directement, en gardant une
public static
référence à elle-même. De cette façon, un Singleton peut contenir une référence à l'instance active, qui serait accessible sans avoir à configurer la référence réelle à chaque fois.Faites-vous référence à l'instance de votre objet?
Il est courant de simplement marquer une référence comme
public
, afin que nous puissions définir la référence à l'instance via l'inspecteur. Vérifiez toujours que vous avez défini la référence à une instance, via l'inspecteur, car il n'est pas rare de manquer cette étape.Instanciez-vous votre instance?
Si nous mettons en place notre objet dans le code, il est important de s'assurer que nous instancions l'objet. Cela peut être effectué en utilisant le
new
mot - clé et les méthodes constructeur. Par exemple, tenez compte des éléments suivants:Nous avons créé une référence à a
GameObject
, mais cela ne signifie rien. L'accès à cette référence telle quelle entraînera une exception de référence nulle . Avant de référencer notreGameObject
instance, nous pouvons appeler une méthode constructeur par défaut comme suit:Le didacticiel Unity sur les classes explique la pratique de la création et de l'utilisation de constructeurs.
Utilisez-vous la
GetComponent<t>()
méthode en supposant que le composant existe?Tout d'abord, assurez-vous que nous appelons toujours
GetComponent<t>()
avant d'appeler des méthodes à partir de l'instance de composant.Pour des raisons qui ne valent pas la peine, nous pouvons supposer que notre objet de jeu local contient un composant particulier et essayer d'y accéder avec
GetComponent<t>()
. Si l'objet de jeu local ne contient pas ce composant particulier, nous retournerons unenull
valeur.Vous pouvez facilement vérifier si la valeur renvoyée est
null
, avant d'y accéder. Cependant, si votre objet de jeu doit avoir le composant requis, il peut être préférable de s'assurer qu'il a au moins une version par défaut de ce composant. Nous pouvons marquer unMonoBehaviour
as[RequireComponent(typeof(t))]
pour nous assurer que nous avons toujours ce type de composant.Voici un exemple de
MonoBehaviour
pour un objet de jeu qui devrait toujours contenir unRigidbody
. Si le script est ajouté à un objet de jeu qui ne contient pas deRigidbody
, une valeur par défautRigidbody
sera créée.Avez-vous essayé de reconstruire votre projet?
Dans certains cas, Unity peut provoquer des problèmes en essayant de référencer une version mise en cache d'un objet de jeu. Conformément à la vieille solution «éteignez-le et rallumez-la», essayez de supprimer votre dossier Bibliothèque et de rouvrir Unity. Unity sera obligé de reconstruire votre projet. Cela peut résoudre certains cas très particuliers de ce problème et devrait signaler des problèmes qui ne se poseraient pas dans une version finale.
la source
Je vois qu'il y a une réponse acceptée. Mais, il y a une meilleure réponse ou suggestion pour la manipulation
NullReferenceException
. Si vous pouvez relier la programmation en langage Java comme moi, vous pouvez empêcher d'envoyer une erreur nulle en utilisant letry-catch
bloc. Essayez-le vous-même! ;-)Si vous utilisez en C #, vérifiez si vous avez
using System;
en haut de votre fichier de script. Sinon, ajoutez-le. Maintenant, vous pouvez utiliser toutes sortes deException
classes tout en essayant d'attraper une ligne de code.Si vous utilisez UnityScript, utilisez
import System;
Voici un exemple:
Rappelez - vous aussi, vous pouvez prendre également d' autres exceptions comme
MissingReferenceException
,MissingComponentException
,IndexOutOfRangeException
, ou toute autre classe d'exception tant que vous incluezusing System
dans votre script.C'est tout.
la source