Karena banyak pengguna menghadapi NullReferenceException: Object reference not set to an instance of an object
kesalahan dalam Unity, saya pikir itu akan menjadi ide yang baik untuk mengumpulkan dari beberapa sumber beberapa penjelasan dan cara untuk memperbaiki kesalahan ini.
Gejala
Saya mendapatkan kesalahan di bawah ini muncul di konsol saya, apa artinya dan bagaimana cara memperbaikinya?
NullReferenceException: Referensi objek tidak disetel ke instance objek
unity
exceptions
Hellium
sumber
sumber
Jawaban:
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 dariMonoBehaviour
) 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
Mengambil komponen yang tidak melekat pada GameObject dan kemudian, mencoba untuk memanipulasinya:
Mengakses GameObject yang tidak ada:
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
:Mengakses elemen array yang tidak diinisialisasi
Lebih jarang, tetapi menjengkelkan jika Anda tidak tahu tentang delegasi C #:
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:
Cara "bersih" (IMHO): Cek
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 menghapusnyaDebug.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 :
Lakukan ini untuk memeriksa apakah setiap referensi diatur:
Bahkan lebih baik :
Sumber:
sumber
try/catch
. Kesalahan memberitahu Anda banyak tentang masalah yang Anda miliki di sana, dan sebelum pemula mulai meletakkan cek nol di mana-mana, masalah utama Anda ada di inspektur saat Anda lupa untuk referensi beberapa objek (seret objek ke skrip). Saya telah melihat banyak kode dengantry/catch
dan membatalkan cek di tempat yang sama sekali tidak perlu. Debugging dan bekerja dengan kode seperti itu adalah "sakit di a **". Pemula belajar tentang kasus penggunaan cek tersebut dan hanya kemudian menggunakannya.else
. MemilikiNullReferenceException
tidak selalu jelas sendiri sementaraNo Rigidbody component attached to the gameObject
langsung menjelaskan apa yang salah. Saya setuju bahwa hanya memilikiif( obj != null )
pesan tanpa hanya "menyembunyikan" masalah, dan Anda dapat memiliki proyek yang berfungsi tetapi tidak melakukan apa yang Anda harapkan tanpa tahu mengapa.Meskipun kami dapat dengan mudah melakukan pemeriksaan untuk memastikan kami tidak mencoba mengakses referensi nol, ini tidak selalu merupakan solusi yang sesuai. Seringkali, dalam pemrograman Unity, masalah kita mungkin berasal dari fakta bahwa referensi tidak boleh nol. Dalam beberapa situasi, mengabaikan referensi nol dapat merusak kode kami.
Sebagai contoh, itu mungkin referensi ke pengontrol input kami. Ini sangat bagus bahwa permainan tidak crash karena pengecualian referensi null, tetapi kita perlu mencari tahu mengapa tidak ada masukan controller, dan memperbaiki yang masalah. Tanpanya, kami memiliki game yang mungkin tidak macet, tetapi tidak dapat mengambil input.
Di bawah ini, saya akan membuat daftar kemungkinan alasan dan solusi, ketika saya menemukan mereka dalam pertanyaan lain.
Apakah Anda mencoba mengakses kelas "manajer"?
Jika Anda mencoba mengakses kelas yang bertindak sebagai "manajer" (yaitu, kelas yang seharusnya hanya memiliki satu instance berjalan pada satu waktu), Anda mungkin lebih baik menggunakan pendekatan Singleton . Kelas Singleton idealnya dapat diakses dari mana saja, langsung, dengan menyimpan
public static
referensi untuk dirinya sendiri. Dengan cara ini, seorang Singleton dapat berisi referensi ke instance aktif, yang akan dapat diakses tanpa kesulitan mengatur referensi aktual setiap saat.Apakah Anda merujuk contoh objek Anda?
Adalah umum untuk hanya menandai referensi
public
, sehingga kita dapat mengatur referensi ke instance melalui inspektur. Selalu periksa apakah Anda telah menetapkan referensi ke instance, melalui inspektur, karena tidak jarang ketinggalan langkah ini.Apakah Anda membuat instance Anda?
Jika kita mengatur objek kita dalam kode, penting untuk memastikan bahwa kita membuat instance objek. Ini dapat dilakukan dengan menggunakan
new
kata kunci dan metode konstruktor. Sebagai contoh, pertimbangkan hal berikut:Kami telah membuat referensi ke a
GameObject
, tetapi tidak menunjuk ke apa pun. Mengakses referensi ini sebagaimana adanya akan menghasilkan pengecualian referensi nol . Sebelum kami mereferensikanGameObject
instance kami , kami dapat memanggil metode konstruktor default sebagai berikut:Tutorial Unity tentang kelas menjelaskan praktik membuat dan menggunakan konstruktor.
Apakah Anda menggunakan
GetComponent<t>()
metode ini dengan asumsi komponen itu ada?Pertama, pastikan bahwa kami selalu memanggil
GetComponent<t>()
sebelum memanggil metode dari instance komponen.Karena alasan yang tidak layak untuk masuk, kami dapat menganggap objek game lokal kami mengandung komponen tertentu, dan mencoba mengaksesnya
GetComponent<t>()
. Jika objek game lokal tidak mengandung komponen tertentu, kami akan mengembalikannull
nilai.Anda dapat dengan mudah memeriksa apakah nilai yang dikembalikan adalah
null
, sebelum mengaksesnya. Namun, jika objek game Anda harus memiliki komponen yang diperlukan, mungkin lebih baik untuk memastikan bahwa itu setidaknya memiliki versi standar dari komponen itu. Kami dapat memberi tagMonoBehaviour
pada[RequireComponent(typeof(t))]
untuk memastikan bahwa kami selalu memiliki jenis komponen itu.Berikut adalah contoh dari
MonoBehaviour
untuk objek game yang harus selalu berisi aRigidbody
. Jika skrip ditambahkan ke objek game yang tidak mengandung aRigidbody
, defaultRigidbody
akan dibuat.Sudahkah Anda mencoba membangun kembali proyek Anda?
Ada beberapa kasus di mana Unity dapat menyebabkan masalah dengan mencoba merujuk versi cache dari objek game. Sejalan dengan solusi "matikan dan nyalakan lagi" yang lama, coba hapus folder Library Anda , dan buka kembali Unity. Persatuan akan dipaksa untuk membangun kembali proyek Anda. Ini dapat memecahkan beberapa contoh masalah yang sangat aneh ini, dan harus menunjuk ke masalah yang tidak akan muncul pada tahap akhir.
sumber
Saya melihat bahwa ada jawaban yang diterima. Tapi, ada jawaban atau saran yang lebih baik bagi Anda untuk menangani
NullReferenceException
. Jika Anda dapat menghubungkan pemrograman dalam bahasa Java seperti saya, Anda dapat mencegah mengirim kesalahan nol dengan menggunakantry-catch
blokir. Cobalah sendiri! ;-)Jika Anda menggunakan dalam C #, periksa apakah Anda memiliki
using System;
di bagian atas file skrip Anda. Jika tidak, tambahkan. Sekarang, Anda dapat menggunakan semua jenisException
kelas sambil mencoba menangkap satu baris kode.Jika Anda menggunakan UnityScript, gunakan
import System;
Ini sebuah contoh:
Juga ingat, Anda dapat menangkap juga pengecualian lain seperti
MissingReferenceException
,MissingComponentException
,IndexOutOfRangeException
, atau kelas eksepsi lain selama Anda termasukusing System
dalam naskah Anda.Itu semuanya.
sumber