एकता में NullReferenceException


11

चूंकि कई उपयोगकर्ताओं को NullReferenceException: Object reference not set to an instance of an objectएकता में त्रुटि का सामना करना पड़ रहा है, मैंने सोचा कि इस स्रोत से कई स्पष्टीकरण और कुछ तरीकों को इकट्ठा करने के लिए एक अच्छा विचार होगा ताकि इस त्रुटि को ठीक किया जा सके।


लक्षण

मुझे अपने कंसोल में दिखाई देने में नीचे त्रुटि हो रही है, इसका क्या मतलब है और मैं इसे कैसे ठीक करूं?

NullReferenceException: ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट की आवृत्ति पर सेट नहीं है


यह एक सामान्य प्रोग्रामिंग प्रश्न की तरह लगता है और गेम विशिष्ट नहीं है। ओपी के स्वयं के प्रश्न के उत्तर में एसओ का एक लिंक शामिल है जो इस विषय को कवर करता है।
पिकालेक

3
जबकि "NullReferenceException", वास्तव में, एक सामान्य प्रोग्रामिंग प्रश्न है, यहाँ, यह प्रश्न विशेष रूप से एकता में अपवाद को शामिल करता है : यह यूनिटी प्रोग्रामिंग में कहाँ सामना किया जा सकता है , और उन्हें कैसे हल किया जाए (विभिन्न उदाहरण देखें)।
हेलियम

@Pikalek, हमने सामान्य प्रोग्रामिंग के संदर्भ में जो भी अनुमति दी है, उसके लिए हमने अपना दायरा बढ़ाया है। जब मैंने इसके बारे में मेटा में पूछा तो यह स्पष्ट किया गया था । मुझे एहसास है, अब, कि यह अभी भी जोश के जवाब के अनुसार 'बहुत सामान्य' के मापदंडों को फिट कर सकता है।
गनीमॉक

वर्तमान जवाब भी कुछ भी की कोई टिप्पणी करता है विशिष्ट एकता के लिए (उदाहरण में एकता विशिष्ट प्रकार का उपयोग कर के अलावा)। यह वास्तव में, एक सामान्य प्रोग्रामिंग प्रतिक्रिया है। हम करीबी तर्कों में उत्तरों का उपयोग नहीं करते हैं, लेकिन यह एक आत्म जवाब है, यह इरादे के समर्थन तर्क की ओर जाता है।
गनीमॉक

3
एकता के पास इन त्रुटियों को ट्रिगर करने के लिए कुछ अनूठे / विशेषता तरीके हैं, बिना असाइन किए गए इंस्पेक्टर फ़ील्ड के माध्यम से, GetComponent या Find प्रयास में विफल रहे, या इसके वैरिएंट फ्लेवर "MissingReferenceException" के माध्यम से जब आपके पास एक वैध संदर्भ था, लेकिन इसे नष्ट () एड मिला। इसलिए, मुझे लगता है कि एकता के संदर्भ में इस प्रश्न का उत्तर समुदाय के लिए उपयोगी होने की अच्छी संभावना है, भले ही अपवाद स्वयं बहुत सामान्य हो।
DMGregory

जवाबों:


14

मान प्रकार बनाम संदर्भ प्रकार

कई प्रोग्रामिंग भाषाओं में, चर को "डेटा प्रकार" कहा जाता है। दो प्राथमिक डेटा प्रकार मूल्य प्रकार (इंट, फ्लोट, बूल, चार, स्ट्रक्चर, ...) और संदर्भ प्रकार (कक्षाओं का उदाहरण) हैं। जबकि मान प्रकारों में स्वयं मान होता है , संदर्भों में एक मेमोरी एड्रेस होता है जो मानों के एक सेट (C / C ++ के समान) को शामिल करने के लिए आवंटित मेमोरी के एक हिस्से की ओर इशारा करता है।

उदाहरण के लिए, Vector3एक मान प्रकार (निर्देशांक और कुछ कार्यों से युक्त एक संरचना) है, जबकि आपके GameObject से जुड़े घटक (जिसमें आपकी कस्टम स्क्रिप्ट शामिल MonoBehaviourहैं) संदर्भ प्रकार हैं।

मेरे पास NullReferenceException कब हो सकती है?

NullReferenceException फेंक दिया जाता है जब आप एक संदर्भ चर का उपयोग करने की कोशिश करते हैं जो किसी भी वस्तु को संदर्भित नहीं कर रहा है, इसलिए यह शून्य है (स्मृति पता 0 की ओर इशारा करता है)।

कुछ सामान्य स्थानों NullReferenceExceptionको उठाया जाएगा:

एक गेमऑब्जेक्ट / घटक में हेरफेर जो निरीक्षक में निर्दिष्ट नहीं किया गया है

// t is a reference to a Transform.
public Transform t ;

private void Awake()
{
     // If you do not assign something to t
     // (either from the Inspector or using GetComponent), t is null!
     t.Translate();
}

एक घटक को पुनः प्राप्त करना जो GameObject से जुड़ा नहीं है और फिर, इसे हेरफेर करने की कोशिश कर रहा है:

private void Awake ()
{
    // Here, you try to get the Collider component attached to your gameobject
    Collider collider = gameObject.GetComponent<Collider>();

    // But, if you haven't any collider attached to your gameobject,
    // GetComponent won't find it and will return null, and you will get the exception.
    collider.enabled = false ;
}

गेमऑबजेक्ट तक पहुँचना मौजूद नहीं है:

private void Start()
{
    // Here, you try to get a gameobject in your scene
    GameObject myGameObject = GameObject.Find("AGameObjectThatDoesntExist");

    // If no object with the EXACT name "AGameObjectThatDoesntExist" exist in your scene,
    // GameObject.Find will return null, and you will get the exception.
    myGameObject.name = "NullReferenceException";
}

नोट: रहो सावधान, GameObject.Find, GameObject.FindWithTag, GameObject.FindObjectOfTypeकेवल gameObjects कि कर रहे हैं वापसी सक्षम पदानुक्रम में जब समारोह कहा जाता है।

एक गटर के परिणाम का उपयोग करने की कोशिश कर रहा है जो वापस आ रहा है null:

var fov = Camera.main.fieldOfView;
// main is null if no enabled cameras in the scene have the "MainCamera" tag.

var selection = EventSystem.current.firstSelectedGameObject;
// current is null if there's no active EventSystem in the scene.

var target = RenderTexture.active.width;
// active is null if the game is currently rendering straight to the window, not to a texture.

एक गैर-प्रारंभिक सरणी के एक तत्व तक पहुंचना

private GameObject[] myObjects ; // Uninitialized array

private void Start()
{
    for( int i = 0 ; i < myObjects.Length ; ++i )
        Debug.Log( myObjects[i].name ) ;
}

यदि आप इसे C # डेलीगेट्स के बारे में नहीं जानते हैं तो कम आम है, लेकिन गुस्सा करना:

delegate double MathAction(double num);

// Regular method that matches signature:
static double Double(double input)
{
    return input * 2;
}

private void Awake()
{
    MathAction ma ;

    // Because you haven't "assigned" any method to the delegate,
    // you will have a NullReferenceException
    ma(1) ;

    ma = Double ;

    // Here, the delegate "contains" the Double method and
    // won't throw an exception
    ma(1) ;
}

कैसे ठीक करना है ?

यदि आप पिछले पैराग्राफ को समझ गए हैं, तो आप जानते हैं कि त्रुटि को कैसे ठीक किया जाए: सुनिश्चित करें कि आपका वैरिएबल किसी वर्ग की आवृत्ति (या प्रतिनिधियों के लिए कम से कम एक फ़ंक्शन) इंगित कर रहा है।

कहना आसान है करना मुश्किल? हाँ सचमुच। समस्या से बचने और पहचानने के लिए यहां कुछ सुझाव दिए गए हैं ।

"गंदा" तरीका: कोशिश और पकड़ने की विधि:

Collider collider = gameObject.GetComponent<Collider>();

try
{
    collider.enabled = false ;
}       
catch (System.NullReferenceException exception) {
    Debug.LogError("Oops, there is no collider attached", this) ;
}

"क्लीनर" तरीका (IMHO): चेक

Collider collider = gameObject.GetComponent<Collider>();

if(collider != null)
{
    // You can safely manipulate the collider here
    collider.enabled = false;
}    
else
{
    Debug.LogError("Oops, there is no collider attached", this) ;
}

जब आप एक त्रुटि का सामना कर रहे हैं, तो आप हमेशा समस्या का कारण ढूंढ सकते हैं। यदि आप "आलसी" हैं (या यदि समस्या को आसानी से हल किया जा सकता है), Debug.Logतो कंसोल जानकारी पर दिखाने के लिए उपयोग करें जो आपको यह पहचानने में मदद करेगा कि समस्या क्या हो सकती है। एक और अधिक जटिल तरीका यह है कि आप अपने आईडीई के ब्रेकपॉइंट और डीबगर का उपयोग करें।

Debug.Logकिस फ़ंक्शन को उदाहरण के लिए पहले कहा जाता है, यह निर्धारित करने के लिए उपयोग करना काफी उपयोगी है। खासकर यदि आपके पास खेतों को प्रारंभिक करने के लिए एक फ़ंक्शन जिम्मेदार है। लेकिन Debug.Logअपने कंसोल (और प्रदर्शन कारणों से) को अव्यवस्थित करने से बचने के लिए उन्हें हटाना न भूलें ।

एक और सलाह, अपने फ़ंक्शन को "कट" करने में संकोच न करें और Debug.Logकुछ चेक बनाने के लिए जोड़ें ।

के बजाय :

 GameObject.Find("MyObject").GetComponent<MySuperComponent>().value = "foo" ;

यह देखने के लिए करें कि क्या हर संदर्भ सेट है:

GameObject myObject = GameObject.Find("MyObject") ;

Debug.Log( myObject ) ;

MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;

Debug.Log( superComponent ) ;

superComponent.value = "foo" ;

और भी बेहतर :

GameObject myObject = GameObject.Find("MyObject") ;

if( myObject != null )
{
   MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
   if( superComponent != null )
   {
       superComponent.value = "foo" ;
   }
   else
   {
        Debug.Log("No SuperComponent found onMyObject!");
   }
}
else
{
   Debug.Log("Can't find MyObject!", this ) ;
}

सूत्रों का कहना है:

  1. http://answers.unity3d.com/questions/47830/what-is-a-null-reference-exception-in-unity.html
  2. /programming/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it/218510#218510
  3. https://support.unity3d.com/hc/en-us/articles/206369473-NullReferenceException
  4. https://unity3d.com/fr/learn/tutorials/topics/scripting/data-types

यह समस्या के निदान के "कैसे" को समझाने के लिए बहुत प्रयास करता है। मैं इस सवाल पर विचार नहीं करूंगा कि प्रश्न का वास्तविक उत्तर " समस्या क्या है "। यह उन उत्तरों को संबोधित करने में भी विफल रहता है जो आमतौर पर इस प्रकार के प्रश्नों पर दिखाई देते हैं। शायद यह StackOverflow प्रलेखन पर बेहतर होगा? शायद नहीं।
Gnemlock

2
मैं यह नहीं कहूंगा कि डीबग लॉग का उपयोग करना आलसी है । मेरे लिए, यह डिबग.लॉग का उपयोग करने के लिए बहुत तेज़ है। जहां त्रुटि हो रही है, उसके दायरे को कम करने के लिए, तो वास्तव में त्रुटि खोजने के लिए डीबगर का उपयोग करें। लेकिन यह हमेशा हाथ में त्रुटि पर निर्भर करता है। किसी भी मामले में, मैं का उपयोग कर यह नहीं कहूंगा डीबग लॉग है आलसी : पी
Vaillancourt

आपको यह भी इंगित करना चाहिए कि यह हमेशा एक अच्छा विचार नहीं है कि अशक्त के लिए चेक लगाया जाए। इससे भी बुरा विचार उपयोग करना होगा try/catch। त्रुटि आपको वहाँ की समस्या के बारे में बहुत कुछ बताती है, और इससे पहले कि शुरुआती हर जगह अशक्त जांच करना शुरू कर दें, आप मुख्य समस्या निरीक्षक में हैं क्योंकि आप कुछ ऑब्जेक्ट (स्क्रिप्ट पर ड्रैग ऑब्जेक्ट) को संदर्भित करना भूल जाते हैं। मैंने उन try/catchजगहों पर बहुत सारे कोड और अशक्त चेक देखे हैं जहां यह पूरी तरह से अनावश्यक है। डिबगिंग और उस तरह के कोड के साथ काम करना "एक ** में दर्द" है। शुरुआती लोग उन चेक के मामलों का उपयोग करने के बारे में सीखते हैं और केवल उनका उपयोग करते हैं।
उम्मीदवार चंद्रमा _Max_

मुझे लगता है कि यदि एक स्पष्ट डिबग संदेश में प्रदान किया जाता है, तो एक अशक्त जांच एक अच्छा विचार हो सकता है else। एक होने के नाते NullReferenceExceptionहमेशा आत्म व्याख्यात्मक नहीं होता है जबकि No Rigidbody component attached to the gameObjectसीधे समझाते हैं कि क्या गलत है। मैं इस बात से सहमत हूं कि if( obj != null )बिना संदेश के सिर्फ समस्या को "छुपाता है", और आपके पास एक काम करने वाला प्रोजेक्ट हो सकता है, लेकिन ऐसा नहीं करने से आप यह जान पाएंगे कि आप क्यों जानते हैं।
हेलियम

4

जबकि हम आसानी से सिर्फ यह सुनिश्चित करने के लिए एक चेक कर सकते हैं कि हम अशक्त संदर्भ तक पहुँचने की कोशिश नहीं कर रहे हैं, यह हमेशा एक उपयुक्त समाधान नहीं है। कई बार, एकता प्रोग्रामिंग में, हमारी समस्या इस तथ्य से उत्पन्न हो सकती है कि संदर्भ शून्य नहीं होना चाहिए । कुछ स्थितियों में, केवल अशक्त संदर्भों को अनदेखा करना हमारे कोड को तोड़ सकता है।

उदाहरण के लिए, यह हमारे इनपुट नियंत्रक का संदर्भ हो सकता है। यह बहुत अच्छा है कि खेल शून्य संदर्भ अपवाद के कारण क्रैश नहीं करता है, लेकिन हमें यह पता लगाने की आवश्यकता है कि कोई इनपुट नियंत्रक क्यों नहीं है, और उस समस्या को ठीक करें । इसके बिना, हमारे पास एक ऐसा खेल है जो दुर्घटनाग्रस्त नहीं हो सकता है, लेकिन इनपुट भी नहीं ले सकता है।

नीचे, मैं संभावित कारणों और समाधानों की सूची दूंगा, क्योंकि मैं अन्य प्रश्नों में उनके पार आता हूं।


क्या आप "प्रबंधक" वर्ग तक पहुंचने का प्रयास कर रहे हैं?

यदि आपकी कक्षा "प्रबंधक" के रूप में कार्य करने की कोशिश कर रही है (यानी, एक ऐसा वर्ग जिसे कभी एक समय में केवल एक उदाहरण होना चाहिए), तो आप सिंगलटन दृष्टिकोण का उपयोग करके बेहतर हो सकते हैं । एक एकल वर्ग को आदर्श रूप से कहीं से भी, सीधे, public staticस्वयं के संदर्भ में रखकर पहुँचा जा सकता है। इस तरह, एक सिंगलटन में सक्रिय उदाहरण का संदर्भ हो सकता है, जो हर बार वास्तविक संदर्भ स्थापित करने की परेशानी के बिना सुलभ होगा।

क्या आप अपनी वस्तु का उदाहरण दे रहे हैं?

यह केवल संदर्भ के रूप में चिह्नित करना आम है public, इसलिए हम इंस्पेक्टर के माध्यम से उदाहरण के लिए संदर्भ सेट कर सकते हैं। हमेशा की जाँच करें आपको लगता है कि है , एक उदाहरण के संदर्भ में निर्धारित करते हैं, निरीक्षक के माध्यम से के रूप में यह असामान्य इस कदम को याद नहीं है।

क्या आप अपनी मिसाल पर अमल कर रहे हैं?

यदि हम कोड में अपना ऑब्जेक्ट सेट कर रहे हैं, तो यह सुनिश्चित करना ज़रूरी है कि हम ऑब्जेक्ट को इंस्टेंट करें। यह newकीवर्ड और कंस्ट्रक्टर विधियों का उपयोग करके किया जा सकता है । उदाहरण के लिए, निम्नलिखित पर विचार करें:

private GameObject gameObject;

हमने एक संदर्भ बनाया है GameObject, लेकिन यह किसी भी बात की ओर इशारा नहीं करता है। इस संदर्भ को एक्सेस करना है के रूप में एक का परिणाम देगा अशक्त संदर्भ अपवाद । हमारे GameObjectउदाहरण का संदर्भ देने से पहले , हम एक डिफ़ॉल्ट कंस्ट्रक्टर विधि को निम्नानुसार कह सकते हैं:

gameObject = new GameObject();

कक्षाओं पर एकता ट्यूटोरियल , रचनाकारों को बनाने और उपयोग करने का अभ्यास बताता है।

क्या आप GetComponent<t>()इस धारणा के साथ विधि का उपयोग कर रहे हैं कि घटक मौजूद है?

सबसे पहले, सुनिश्चित करें कि GetComponent<t>()घटक घटक से तरीकों को कॉल करने से पहले हम हमेशा कॉल करते हैं।

अंदर जाने के लायक नहीं होने के कारण, हम मान सकते हैं कि हमारी स्थानीय गेम ऑब्जेक्ट में एक विशेष घटक है, और इसके साथ एक्सेस करने का प्रयास करें GetComponent<t>()। स्थानीय खेल वस्तु होती है, तो नहीं है कि विशेष घटक होते हैं, हम एक वापस आ जाएगी nullमूल्य।

आप आसानी से देख सकते हैं कि रिटर्निंग वैल्यू है null, इसे एक्सेस करने से पहले। हालांकि, यदि आपके गेम ऑब्जेक्ट में आवश्यक घटक होना चाहिए , तो यह सुनिश्चित करना बेहतर हो सकता है कि इसमें कम से कम उस घटक का डिफ़ॉल्ट संस्करण हो। हम एक टैग कर सकते हैं MonoBehaviourके रूप में [RequireComponent(typeof(t))]सुनिश्चित करने के लिए हम हमेशा घटक के प्रकार की है।

यहां MonoBehaviourएक गेम ऑब्जेक्ट के लिए एक उदाहरण है जिसमें हमेशा एक होना चाहिए Rigidbody। यदि स्क्रिप्ट को एक गेम ऑब्जेक्ट में जोड़ा जाता है जिसमें एक नहीं होता है Rigidbody, तो एक डिफ़ॉल्ट Rigidbodyबनाया जाएगा।

[RequireComponent(typeof(Rigidbody))]
public class AlwaysHasRigidbody : MonoBehaviour
{
    Rigidbody myRigidbody;


    void Start()
    {
        myRigidbody = GetComponent<Rigidbody>();
    }
}

क्या आपने अपनी परियोजना को फिर से बनाने की कोशिश की है?

ऐसे कुछ मामले हैं जहां एकता एक गेम ऑब्जेक्ट के कैश्ड संस्करण को संदर्भित करने की कोशिश करके समस्याएं पैदा कर सकती है । पुरानी उम्र के अनुसार "इसे बंद करें और फिर से" समाधान के साथ, अपने लाइब्रेरी फ़ोल्डर को हटाने की कोशिश करें , और एकता को फिर से खोलें। एकता को अपनी परियोजना को फिर से बनाने के लिए मजबूर किया जाएगा। यह इस समस्या के कुछ बहुत अजीब उदाहरणों को हल कर सकता है, और उन मुद्दों को इंगित करना चाहिए जो अंतिम निर्माण में नहीं आएंगे।


1
मुझे अभी भी यकीन नहीं है कि यह सवाल विषय पर होना चाहिए। लेकिन यहां उपयोगकर्ताओं के लिए अतिरिक्त संभावित उत्तर पोस्ट करने के लिए एक समुदाय विकि है; अब तक यह एकता और "अशक्त संदर्भ" (जो वास्तव में प्रश्न के मानदंडों को पूरा करता है) के रूप में चिह्नित प्रश्नों के लिए स्वीकृत उत्तरों के पहले आधे पृष्ठ की मूल बातें शामिल है ।
Gnemlock

-5

मैं देख रहा हूं कि एक स्वीकृत उत्तर है। लेकिन, हैंडलिंग के लिए आपके लिए बेहतर उत्तर या सुझाव है NullReferenceException। यदि आप मेरी तरह जावा भाषा में प्रोग्रामिंग से संबंधित कर सकते हैं, तो आप try-catchब्लॉक का उपयोग करके एक अशक्त त्रुटि भेजने से रोक सकते हैं । अपने लिए कोशिश करो! ;-)

यदि आप C # का उपयोग कर रहे हैं, तो जांचें कि क्या आपके पास using System;आपकी स्क्रिप्ट फ़ाइल के शीर्ष पर है। यदि नहीं, तो इसे जोड़ें। अब, आप Exceptionकोड की एक पंक्ति को आज़माते हुए सभी प्रकार की कक्षाओं का उपयोग कर सकते हैं ।

यदि आप UnityScript का उपयोग कर रहे हैं, तो उपयोग करें import System;

यहाँ एक उदाहरण है:

using System; // --> This exact line of code. That's it.
using UnityEngine;

public class Test : MonoBehaviour {

    public GameObject player; // --> Example to check if there's a null content;

    public void Update() {

        // You may now catch null reference here.
        try {

            player.transform.Translate(0, 0, 2);

        } catch(NullReferenceException e) { // --> You may use this type of exception class

        }

    }
}

यह भी याद रखें, आप भी इस तरह के रूप में अन्य अपवाद पकड़ कर सकते हैं MissingReferenceException, MissingComponentException, IndexOutOfRangeException, जब तक आप शामिल रूप में या किसी अन्य अपवाद कक्षाओं using Systemअपनी स्क्रिप्ट में।

बस इतना ही।


2
कोशिश और पकड़ने की विधि को स्वीकृत उत्तर में वर्णित किया गया है ....
हेलियम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.