Jenis nilai vs jenis referensi
Dalam banyak bahasa pemrograman, variabel memiliki apa yang disebut "tipe data". Dua tipe data primer adalah tipe nilai (int, float, bool, char, struct, ...) dan tipe referensi (instance dari kelas). Sementara tipe nilai mengandung nilai itu sendiri , referensi berisi alamat memori yang menunjuk ke bagian memori yang dialokasikan untuk berisi satu set nilai (mirip dengan C / C ++).
Misalnya, Vector3
adalah tipe nilai (struct yang berisi koordinat dan beberapa fungsi) sementara komponen yang dilampirkan ke GameObject Anda (termasuk skrip kustom Anda yang diwarisi dari MonoBehaviour
) adalah tipe referensi.
Kapan saya dapat memiliki NullReferenceException?
NullReferenceException
dilemparkan ketika Anda mencoba mengakses variabel referensi yang tidak mereferensikan objek apa pun, maka itu adalah nol (alamat memori menunjuk ke 0).
Beberapa tempat umum a NullReferenceException
akan dimunculkan:
Memanipulasi GameObject / Komponen yang belum ditentukan dalam inspektur
// 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();
}
Mengambil komponen yang tidak melekat pada GameObject dan kemudian, mencoba untuk memanipulasinya:
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 ;
}
Mengakses GameObject yang tidak ada:
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";
}
Catatan: Hati-hati, GameObject.Find
, GameObject.FindWithTag
, GameObject.FindObjectOfType
hanya kembali gameObjects yang diaktifkan dalam hirarki ketika fungsi ini dipanggil.
Mencoba menggunakan hasil pengambil yang kembali 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.
Mengakses elemen array yang tidak diinisialisasi
private GameObject[] myObjects ; // Uninitialized array
private void Start()
{
for( int i = 0 ; i < myObjects.Length ; ++i )
Debug.Log( myObjects[i].name ) ;
}
Lebih jarang, tetapi menjengkelkan jika Anda tidak tahu tentang delegasi 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) ;
}
Bagaimana cara memperbaiki ?
Jika Anda telah memahami paragraf sebelumnya, Anda tahu cara memperbaiki kesalahan: pastikan variabel Anda merujuk (menunjuk ke) instance kelas (atau mengandung setidaknya satu fungsi untuk delegasi).
Lebih mudah diucapkan daripada dilakukan? Ya memang. Berikut adalah beberapa tips untuk menghindari dan mengidentifikasi masalah.
Cara "kotor": Metode coba & tangkap:
Collider collider = gameObject.GetComponent<Collider>();
try
{
collider.enabled = false ;
}
catch (System.NullReferenceException exception) {
Debug.LogError("Oops, there is no collider attached", this) ;
}
Cara "bersih" (IMHO): Cek
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) ;
}
Saat menghadapi kesalahan yang tidak bisa Anda selesaikan, selalu merupakan ide bagus untuk menemukan penyebab masalahnya. Jika Anda "malas" (atau jika masalahnya dapat dipecahkan dengan mudah), gunakan Debug.Log
untuk memperlihatkan informasi konsol yang akan membantu Anda mengidentifikasi apa yang dapat menyebabkan masalah. Cara yang lebih kompleks adalah dengan menggunakan Breakpoints dan Debugger dari IDE Anda.
Penggunaannya Debug.Log
cukup berguna untuk menentukan fungsi mana yang disebut pertama misalnya. Terutama jika Anda memiliki fungsi yang bertanggung jawab untuk menginisialisasi bidang. Tapi jangan lupa untuk menghapusnya Debug.Log
agar tidak mengacaukan konsol Anda (dan karena alasan kinerja).
Saran lain, jangan ragu untuk "memotong" panggilan fungsi Anda dan menambahkan Debug.Log
untuk melakukan beberapa pemeriksaan.
Dari pada :
GameObject.Find("MyObject").GetComponent<MySuperComponent>().value = "foo" ;
Lakukan ini untuk memeriksa apakah setiap referensi diatur:
GameObject myObject = GameObject.Find("MyObject") ;
Debug.Log( myObject ) ;
MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
Debug.Log( superComponent ) ;
superComponent.value = "foo" ;
Bahkan lebih baik :
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 ) ;
}
Sumber:
- 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