Değer türü ve Referans türü
Birçok programlama dilinde, değişkenler "veri tipi" olarak adlandırılır. İki birincil veri türü değer türleridir (int, float, bool, char, struct, ...) ve başvuru tipidir (sınıf örneği). Değer türleri değerin kendisini içermekle birlikte , başvurular belleğin bir değer kümesi (C / C ++ 'a benzer) içerecek şekilde ayrılmış bir bölümünü gösteren bir bellek adresi içerir .
Örneğin Vector3
, bir değer türüdür (koordinatları ve bazı işlevleri içeren bir yapı MonoBehaviour
).
Ne zaman bir NullReferenceException olabilir?
NullReferenceException
herhangi bir nesneye başvurmayan bir referans değişkenine erişmeye çalıştığınızda atılır, bu nedenle null olur (bellek adresi 0'ı gösterir).
Bazı ortak yerler NullReferenceException
yükseltilecek:
Müfettişte belirtilmemiş bir GameObject / Bileşeni değiştirme
// 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'e bağlı olmayan bir bileşeni almak ve sonra onu değiştirmeye çalışmak:
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 ;
}
Mevcut olmayan bir GameObject öğesine erişme:
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";
}
Not: Be dikkatli, GameObject.Find
, GameObject.FindWithTag
, GameObject.FindObjectOfType
okunur gameObjects dönmek etkin işlev çağrıldığında hiyerarşisinde.
Geri dönen bir alıcı sonucunu kullanmaya çalışmak 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.
Başlatılmamış bir dizinin elemanına erişme
private GameObject[] myObjects ; // Uninitialized array
private void Start()
{
for( int i = 0 ; i < myObjects.Length ; ++i )
Debug.Log( myObjects[i].name ) ;
}
Daha az yaygın, ancak C # delegeleri hakkında bilmiyorsanız sinir bozucu:
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) ;
}
Nasıl düzeltilir ?
Önceki paragrafları anladıysanız, hatayı nasıl düzeltebileceğinizi biliyorsunuzdur: değişkeninizin bir sınıf örneğine (veya temsilciler için en az bir işlev içerdiğine) işaret ettiğinden emin olun.
Söylemesi yapmaktan kolay? Evet kesinlikle. Sorunu önlemek ve tanımlamak için bazı ipuçları .
"Kirli" yol: try & catch yöntemi:
Collider collider = gameObject.GetComponent<Collider>();
try
{
collider.enabled = false ;
}
catch (System.NullReferenceException exception) {
Debug.LogError("Oops, there is no collider attached", this) ;
}
"Daha temiz" yol (IMHO): Çek
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) ;
}
Çözemediğiniz bir hatayla karşılaştığınızda , sorunun nedenini bulmak her zaman iyi bir fikirdir. "Tembel" iseniz (veya sorun kolayca çözülebiliyorsa), Debug.Log
konsol bilgisinde soruna neyin neden olabileceğini belirlemenize yardımcı olacak gösterimi kullanın . Daha karmaşık bir yol, IDE'nizin Kesme Noktalarını ve Hata Ayıklayıcısını kullanmaktır.
Debug.Log
Örneğin, ilk olarak hangi işlevin çağrıldığını belirlemek için kullanmak oldukça yararlıdır. Özellikle alanları başlatmaktan sorumlu bir fonksiyonunuz varsa. Ancak Debug.Log
konsolunuzu karmaşıklaştırmaktan (ve performans nedenlerinden dolayı) bunları kaldırmayı unutmayın .
Başka bir tavsiye, fonksiyon çağrılarını "kesmek" ve Debug.Log
bazı kontroller yapmak için tereddüt etmeyin .
Onun yerine :
GameObject.Find("MyObject").GetComponent<MySuperComponent>().value = "foo" ;
Her referansın ayarlanıp ayarlanmadığını kontrol etmek için bunu yapın:
GameObject myObject = GameObject.Find("MyObject") ;
Debug.Log( myObject ) ;
MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
Debug.Log( superComponent ) ;
superComponent.value = "foo" ;
Daha iyi :
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 ) ;
}
Kaynaklar:
- http://answers.unity3d.com/questions/47830/what-is-a-null-reference-exception-in-unity.html
- /programming/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it/218510#218510
- https://support.unity3d.com/hc/en-us/articles/206369473-NullReferenceException
- https://unity3d.com/fr/learn/tutorials/topics/scripting/data-types