Ada beberapa situasi dengan iOS di mana aplikasi Anda bekerja sempurna di Editor Unity tetapi kemudian tidak bekerja atau mulai di perangkat. Masalahnya sering berhubungan dengan kode atau kualitas konten. Bagian ini menjelaskan skenario paling umum.
Ada sejumlah alasan mengapa ini mungkin terjadi. Penyebab umum termasuk:
Pesan ini biasanya muncul di perangkat iOS ketika aplikasi Anda menerima NullReferenceException. Ada dua cara untuk mengetahui di mana kesalahan terjadi:
Unity termasuk penanganan berbasis perangkat lunak NullReferenceException. compiler AOT mencakup cek cepat untuk referensi null setiap kali metode atau variabel diakses pada objek. Fitur ini mempengaruhi kinerja skrip, itulah sebabnya diaktifkan hanya untuk development buildsMembangun pengembangan termasuk simbol debug dan memungkinkan Profiler. More info
Lihat di Glossary (meningkatkan opsi WordPress.org dalam dialog Build Settings). Jika semuanya dilakukan dengan benar dan kesalahan sebenarnya terjadi di . Kode NET kemudian Anda tidak akan melihat EXC_BAD_ACCESS lagi. Sebagai gantinya, teks pengecualian .NET akan dicetak di konsol Xcode (atau kode Anda hanya akan menanganinya dalam pernyataan “catch”). Output khas mungkin:
Unhandled Exception: System.NullReferenceException: A null value was found where an object instance was required.
at DayController+$handleTimeOfDay$121+$.MoveNext () [0x0035a] in DayController.js:122
Ini menunjukkan bahwa kesalahan terjadi dalam metode handleTimeOfDay dari kelas DayController, yang bekerja sebagai koroutine. Juga, jika itu adalah kode skrip maka Anda umumnya akan diberitahukan nomor garis yang tepat (misalnya “DayController.js:122”). Garis offending mungkin sesuatu seperti berikut:
Instantiate(_imgwww.assetBundle.mainAsset);
Ini mungkin terjadi jika, katakanlah, script mengakses bundel aset tanpa pemeriksaan pertama yang diunduh dengan benar.
Jejak tumpukan asli adalah alat yang jauh lebih kuat untuk penyelidikan kesalahan tetapi menggunakannya membutuhkan beberapa keahlian. Juga, Anda umumnya tidak bisa melanjutkan setelah kesalahan memori asli (hardware memori). Untuk mendapatkan jejak tumpukan asli, ketik bt all ke Xcode Debugger Console. Periksa jejak stack yang dicetak; mereka mungkin mengandung petunjuk tentang di mana kesalahan terjadi. Anda mungkin melihat sesuatu seperti:
...
Thread 1 (thread 11523):
1. 0 0x006267d0 in m_OptionsMenu_Start ()
1. 1 0x002e4160 in wrapper_runtime_invoke_object_runtime_invoke_void__this___object_intptr_intptr_intptr ()
1. 2 0x00a1dd64 in mono_jit_runtime_invoke (method=0x18b63bc, obj=0x5d10cb0, params=0x0, exc=0x2fffdd34) at /Users/mantasp/work/unity/unity-mono/External/Mono/mono/mono/mini/mini.c:4487
1. 3 0x0088481c in MonoBehaviour::InvokeMethodOrCoroutineChecked ()
...
Pertama, Anda harus menemukan jejak stack untuk “Thread 1”, yang merupakan benang utama. Garis pertama dari jejak stack akan menunjuk ke tempat di mana kesalahan terjadi. Dalam contoh ini, jejak menunjukkan bahwa NullReferenceException terjadi di dalam metode OptionsMenu skrip Start. Melihat dengan hati-hati pada implementasi metode ini akan mengungkapkan penyebab masalah. Biasanya, NullReferenceExceptions terjadi dalam metode Start ketika asumsi yang salah dibuat tentang urutan awalisasi. Dalam beberapa kasus hanya jejak tumpukan parsial terlihat pada Konsol Debugger:
Thread 1 (thread 11523):
1. 0 0x0062564c in start ()
Ini menunjukkan bahwa simbol asli dilucuti selama peluncuran aplikasi. Jejak stack penuh dapat diperoleh dengan prosedur berikut:
Ini biasanya terjadi ketika perpustakaan eksternal disusun dengan set instruksi ARM Thumb. Saat ini, perpustakaan tersebut tidak kompatibel dengan Unity. Masalahnya dapat diselesaikan dengan mudah dengan mengulangi perpustakaan tanpa instruksi Thumb. Anda dapat melakukan ini untuk proyek Xcode perpustakaan dengan langkah-langkah berikut:
Jika sumber perpustakaan tidak tersedia Anda harus meminta pemasok untuk versi non-thumb perpustakaan.
Kadang-kadang, Anda mungkin melihat pesan seperti Program menerima sinyal: “0”. Pesan peringatan ini sering tidak fatal dan hanya menunjukkan bahwa iOS rendah pada memori dan meminta aplikasi untuk membebaskan beberapa memori. Biasanya, proses latar belakang seperti Mail akan membebaskan beberapa memori dan aplikasi Anda dapat terus berjalan. Namun, jika aplikasi Anda terus menggunakan memori atau meminta lebih, OS akhirnya akan mulai membunuh aplikasi dan Anda bisa menjadi salah satu dari mereka. Apple tidak mendokumentasikan apa penggunaan memori yang aman, tetapi observasi empiris menunjukkan bahwa aplikasi menggunakan kurang dari 50% dari semua perangkat RAM tidak memiliki masalah penggunaan memori utama. metrik utama Anda harus mengandalkan adalah berapa banyak RAM penggunaan aplikasi Anda. Penggunaan memori aplikasi Anda terdiri dari tiga komponen utama:
Sitemap Note: hanya menunjukkan heap yang dialokasikan oleh .NET Profiler internal. Total penggunaan memori dapat ditentukan melalui Instrumen Xcode seperti yang ditunjukkan di atas. Gambar ini termasuk bagian dari biner aplikasi, beberapa penyangga kerangka standar, penyangga state internal mesin Unity, landak runtime .NET (angka dicetak oleh profiler internal), driver GLES heap dan beberapa hal miscellan lainnya.scriptsSepotong kode yang memungkinkan Anda untuk membuat Komponen Anda sendiri, memicu peristiwa permainan, memodifikasi sifat komponen dari waktu ke waktu dan menanggapi input pengguna dengan cara apa pun yang Anda sukai. More info
Lihat di Glossary. Total memory usage can be determined via Xcode Instruments as shown above. This figure includes parts of the application binary, some standard framework buffers, Unity engine internal state buffers, the .NET runtime heap (number printed by internal profiler), GLES driver heap and some other miscellaneous stuff.
Alat lain menampilkan semua alokasi yang dibuat oleh aplikasi Anda dan menyertakan statistik heap asli dan berhasil. Statistik penting adalah nilai Net bytes.
Untuk menjaga penggunaan memori rendah:
Querying OS tentang jumlah memori gratis mungkin tampak seperti ide yang baik untuk mengevaluasi seberapa baik aplikasi Anda berkinerja. Namun, statistik memori gratis kemungkinan tidak dapat diandalkan karena OS menggunakan banyak penyangga dinamis dan cache. Satu-satunya pendekatan yang dapat diandalkan adalah untuk melacak konsumsi memori untuk aplikasi Anda dan gunakan yang sebagai metrik utama. Perhatikan bagaimana grafik dari alat yang dijelaskan di atas perubahan seiring waktu, terutama setelah memuat tingkat baru.
Ada beberapa alasan untuk ini. Anda perlu memeriksa log perangkat untuk mendapatkan rincian lebih lanjut. Hubungkan perangkat ke Mac Anda, luncurkan Xcode dan pilih Window > Devices and Simulators dari menu. Pilih perangkat Anda di bilah alat kiri jendela, lalu klik pada tombol Show the device console dan meninjau pesan terbaru dengan hati-hati. Selain itu, Anda mungkin perlu untuk menyelidiki laporan kecelakaan. Anda dapat mengetahui bagaimana memperoleh laporan kecelakaan di sini: http://developer.apple.com/iphone/library/technotes/tn2008/tn2151.html.
Ada batas waktu yang kurang didokumentasikan untuk aplikasi iOS untuk membuat bingkai pertama dan input proses. Jika aplikasi Anda melebihi batas ini, itu akan dibunuh oleh SpringBoard. Ini mungkin terjadi dalam aplikasi dengan sceneAdegan berisi lingkungan dan menu permainan Anda. Pikirkan setiap file Adegan unik sebagai tingkat yang unik. Di setiap Adegan, Anda menempatkan lingkungan, hambatan, dan dekorasi, pada dasarnya merancang dan membangun permainan Anda dalam potongan-potongan. More info
Lihat di Glossary pertama yang terlalu besar, misalnya. Untuk menghindari masalah ini, disarankan untuk membuat adegan awal kecil yang hanya menampilkan layar percikan, tunggu bingkai atau dua dengan yield dan kemudian mulai memuat adegan nyata. Ini dapat dilakukan dengan kode sesederhana berikut:
IEnumerator Start() {
yield return new WaitForEndOfFrame();
// Do not forget using UnityEngine.SceneManagement directive
SceneManager.LoadScene("Test");
}
Saat ini Type.GetProperty() dan Type.GetValue() didukung hanya untuk profil .NET 2.0 Subset. Anda dapat memilih . Tingkat kompatibilitas API NET dalam pengaturan Player.
Note: Type.GetProperty() dan Type.GetValue() mungkin tidak kompatibel dengan pengupasan kode yang dikelola dan mungkin perlu dikecualikan (Anda dapat menyediakan daftar tipe non-strippable kustom selama proses pengupasan untuk menyelesaikan ini). Untuk rincian lebih lanjut, lihat Panduan optimasi ukuran pemain iOS.
Implementasi Mono .NET untuk iOS didasarkan pada teknologi AOT (kepala kompilasi waktu ke kode asli), yang memiliki keterbatasannya. Ini hanya mengumpulkan metode jenis generik (di mana jenis nilai digunakan sebagai parameter generik) yang secara eksplisit digunakan oleh kode lain. Ketika metode tersebut digunakan hanya melalui refleksi atau dari kode asli (yaitu sistem serialisasi) maka mereka mendapatkan skipped selama AOT compilationAhead of Time (AOT) kompilasi adalah metode optimasi yang digunakan oleh semua platform kecuali iOS untuk mengoptimalkan ukuran pemain yang dibangun. . More info
Lihat di Glossary. compiler AOT dapat dihindari untuk menyertakan kode dengan menambahkan metode perut di suatu tempat dalam kode skrip. Ini dapat merujuk pada metode yang hilang dan sehingga mendapatkan mereka dikompilasi ke depan waktu.
void _unusedMethod() {
var tmp = new SomeType<SomeValueType>();
}
Sitemap Jenis nilai adalah jenis dasar, mendirikan dan merusak.Note: Value types are basic types, enums and structs.
Sitemap Login Layanan kriptografi sangat bergantung pada refleksi dan tidak kompatibel dengan pengupasan kode yang dikelola karena ini melibatkan analisis kode statis. Kadang-kadang solusi termudah untuk kecelakaan adalah untuk mengecualikan seluruh ruang nama System.Security.Crypography dari proses pengupasan.
Proses pengupasan dapat disesuaikan dengan menambahkan file link.xml kustom ke folder Assets proyek Unity Anda. Ini menentukan jenis dan namespace yang harus dikecualikan dari pengupasan. Rincian lebih lanjut dapat ditemukan di Panduan optimasi ukuran pemain iOS.
<linker>
<assembly fullname="mscorlib">
<namespace fullname="System.Security.Cryptography" preserve="all"/>
</assembly>
</linker>
Anda harus mempertimbangkan saran di atas atau mencoba bekerja di sekitar masalah ini dengan menambahkan referensi tambahan ke kelas spesifik untuk kode skrip Anda:
object obj = new MD5CryptoServiceProvider();
Kesalahan ini biasanya terjadi jika Anda menggunakan banyak generik berulang. Anda dapat mengintip kompilator AOT untuk mengalokasikan lebih banyak trampolines tipe 0, tipe 1 atau tipe 2. Pilihan baris perintah kompiler tambahan dapat ditentukan dalam bagian Other Settings dari pengaturan Player. Untuk tipe 0 trampolines menentukan ntrampolines=ABCD
, di mana ABCD adalah jumlah trampolines baru yang diperlukan (yaitu 4096). Untuk tipe 1 trampolines menentukan nrgctx-trampolines=ABCD
dan untuk tipe 2 trampolines menentukan nimt-trampolines=ABCD
.
Sitemap Xcode rilis ada perubahan yang diperkenalkan di alat kompresi dan optimasi PNG. Perubahan ini mungkin menyebabkan positif palsu dalam pemeriksaan runtime iOS Unity untuk modifikasi layar percikan. Jika Anda menghadapi masalah tersebut mencoba upgrade Unity ke versi terbaru yang tersedia secara publik. Jika ini tidak membantu, Anda mungkin mempertimbangkan pekerjaan berikut:
Jika ini masih tidak membantu mencoba menonaktifkan rekompresi PNG di Xcode:
Kesalahan yang paling umum adalah untuk mengasumsikan bahwa unduhan www selalu terjadi pada benang terpisah. Di beberapa platform ini mungkin benar, tetapi Anda tidak harus mengambilnya untuk diberikan. Cara terbaik untuk melacak status WWW adalah baik untuk menggunakan pernyataan yield atau status cek dalam metode Update. Anda harus not menggunakan lingkaran while sibuk untuk itu.
Beberapa operasi dengan UI(User Interface) Memungkinkan pengguna untuk berinteraksi dengan aplikasi Anda. Unity saat ini mendukung tiga sistem UI. More info
Lihat di Glossary akan menghasilkan iOS menarik kembali jendela segera (misalnya yang paling umum menambahkan UIView dengan UIViewController ke UIWindow utama). Jika Anda memanggil fungsi asli dari skrip, itu akan terjadi di dalam PlayerLoop Unity, mengakibatkan PlayerLoop disebut berulang. Dalam kasus seperti itu, Anda harus mempertimbangkan menggunakan metode performSelectorOnMainThread dengan set waitUntilDone untuk palsu. Ini akan memberi tahu iOS untuk menjadwalkan operasi untuk menjalankan panggilan Unity's PlayerLoop.
Jika aplikasi Anda berjalan ok di editor tetapi Anda mendapatkan kesalahan dalam proyek iOS Anda ini dapat disebabkan oleh hilang DLLs (misalnya I18N.dll, I19N.West.dll). Dalam kasus ini, coba salin mereka dll dari dalam Unity. aplikasi ke folder Assets\Plugins proyek Anda. Lokasi DLL dalam aplikasi kesatuan adalah: WordPress.org Anda harus juga memeriksa tingkat pengupasan proyek Anda untuk memastikan kelas di DLLs tidak dihapus ketika build dioptimalkan. Lihatlah Halaman Optimasi iOS untuk informasi lebih lanjut tentang tingkat pengupasan iOS.
Biasanya, pesan seperti itu diterima ketika fungsi yang dikelola delegate dilewatkan ke fungsi asli, tetapi kode pembungkus yang diperlukan tidak dihasilkan ketika aplikasi dibangun. Anda dapat membantu kompilasi AOT dengan petunjuk metode mana yang akan dilewatkan sebagai delegasi ke kode asli. Ini dapat dilakukan dengan menambahkan atribut kustom MonoPInvokeCallbackAttribute. Saat ini, hanya metode statis dapat dilewatkan sebagai delegasi ke kode asli.
Kode sampel:
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
using AOT;
public class NewBehaviourScript : MonoBehaviour {
[DllImport ("__Internal")]
private static extern void DoSomething (NoParamDelegate del1, StringParamDelegate del2);
delegate void NoParamDelegate ();
delegate void StringParamDelegate (string str);
[MonoPInvokeCallback(typeof(NoParamDelegate))]
public static void NoParamCallback() {
Debug.Log ("Hello from NoParamCallback");
}
[MonoPInvokeCallback(typeof(StringParamDelegate))]
public static void StringParamCallback(string str) {
Debug.Log(string.Format("Hello from StringParamCallback {0}", str));
}
// Use this for initialization
void Start() {
DoSomething(NoParamCallback, StringParamCallback);
}
}
Kesalahan ini biasanya berarti ada cukup banyak kode dalam modul tunggal. Biasanya, disebabkan oleh memiliki banyak kode skrip atau memiliki eksternal besar. Rakitan NET termasuk dalam membangun. Dan memungkinkan debugging script mungkin membuat hal-hal lebih buruk, karena menambahkan beberapa instruksi tambahan untuk setiap fungsi, sehingga lebih mudah untuk memukul batas itu.
Mengaktifkan pengupasan kode yang dikelola dalam pengaturan Player mungkin membantu dengan masalah ini, terutama jika eksternal besar. Rakitan NET terlibat. Tetapi jika masalah berlanjut maka solusi terbaik adalah membagi kode skrip pengguna menjadi beberapa rakitan. Cara termudah untuk ini adalah memindahkan beberapa kode ke folder Plugins. Kode di lokasi ini dimasukkan ke perakitan yang berbeda. Juga, periksa informasi tentang bagaimana nama folder khusus mempengaruhi kompilasi skrip.