API
Pelaporan kecelakaan bug di iOS

Pemecahan Masalah pada perangkat iOS

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.

Permainan berhenti merespons setelah beberapa saat. Xcode menunjukkan “interrupted” di bar status.

Ada sejumlah alasan mengapa ini mungkin terjadi. Penyebab umum termasuk:

  • Kesalahan scripting seperti menggunakan variabel yang tidak diinisialisasi, dll.
  • Menggunakan pihak ketiga Thumb disusun perpustakaan asli. Perpustakaan seperti itu memicu masalah yang diketahui di linker SDK iOS dan mungkin menyebabkan kecelakaan acak.
  • Menggunakan jenis generik dengan jenis nilai sebagai parameter (misalnya Daftar <int>, Daftar <SomeStruct>, Daftar <SomeEnum>) untuk properti skrip serializable.
  • Menggunakan refleksi ketika pengupasan kode yang dikelola diaktifkan.
  • Kesalahan dalam antarmuka plugin asli (tanda tangan metode kode yang dikelola tidak sesuai dengan tanda tangan fungsi kode asli). Informasi dari konsol Debugger XCode sering dapat membantu mendeteksi masalah ini (Menu Xcode: View > Debug Area > Activate Console).

The Xcode console shows "Program received signal: “SIGBUS” or EXC_BAD_ACCESS error.

Pesan ini biasanya muncul di perangkat iOS ketika aplikasi Anda menerima NullReferenceException. Ada dua cara untuk mengetahui di mana kesalahan terjadi:

Jejak stack terkelola

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

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:

  • Hapus aplikasi dari perangkat.
  • Bersihkan semua target.
  • Membangun dan menjalankan.
  • Dapatkan jejak stack lagi seperti yang dijelaskan di atas.

EXC_BAD_ACCESS dimulai ketika perpustakaan eksternal dikaitkan dengan aplikasi Unity iOS.

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:

  • Di Xcode, pilih View > Navigators > Show Project Navigator dari menu
  • Pilih proyek Unity-iPhone, aktifkan tab Build Settings tab
  • Di bidang pencarian masuk: Other C Flags
  • Tambahkan bendera Login Login di sana dan membangun kembali perpustakaan.

Jika sumber perpustakaan tidak tersedia Anda harus meminta pemasok untuk versi non-thumb perpustakaan.

Konsol Xcode menunjukkan “WARNING -> aplikasiDidReceiveMemoryWarning()” dan aplikasi crash segera setelahnya

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:

  • Kode aplikasi (OS perlu memuat dan menyimpan kode aplikasi Anda di RAM, tetapi beberapa mungkin dibuang jika benar-benar diperlukan)
  • Heap asli (digunakan oleh mesin untuk menyimpan keadaannya, aset Anda, dll. di RAM)
  • Dikelola heap (digunakan oleh runtime Mono Anda untuk menjaga C # objek)
  • Kolam memori driver GLES: tekstur, bingkaibuffers, dikompilasi shadersProgram yang berjalan di GPU. More info
    Lihat di Glossary
    , dll. Penggunaan memori aplikasi Anda dapat dilacak oleh dua alat Instrumen Xcode: Activity Monitor dan Allocations. Anda dapat mulai dari menu Xcode Run: Product > Profile dan kemudian pilih alat khusus atau melalui Xcode > Open Developer Tools > Instruments. Alat Activity Monitor menunjukkan semua statistik proses termasuk Real memory yang dapat dianggap sebagai jumlah total RAM yang digunakan oleh aplikasi Anda. Kombinasi versi HW Note: OS dan perangkat HW mungkin dapat mempengaruhi jumlah penggunaan memori, sehingga Anda harus berhati-hati ketika membandingkan nomor yang diperoleh pada perangkat yang berbeda.

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.

Permainan berjalan dengan benar ketika diluncurkan dari Xcode tetapi crash saat memuat tingkat pertama ketika meluncurkan secara manual di perangkat.

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.

Konsol Penyelenggara Xcode berisi pesan “terampilkan oleh SpringBoard”.

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");
}

Type.GetProperty() atau Type.GetValue() menyebabkan crash pada perangkat

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.

Permainan crash dengan pesan kesalahan “ExecutionEngineException: Meninggalkan ke metode kompilasi JIT ‘SometType`1 <SomeValueType>:.ctor ()’ sambil berjalan dengan -aot-only. Sitemap

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.

Berbagai crash terjadi pada perangkat ketika kombinasi sistem. Login Cryptography dan garis kode yang dikelola digunakan

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.

WordPress.org

<linker>
       <assembly fullname="mscorlib">
               <namespace fullname="System.Security.Cryptography" preserve="all"/>
       </assembly>
</linker>

Aplikasi crash saat menggunakan Sistem.Security.Cryptography.MD5 dengan pengupasan kode yang dikelola

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();

“Ran dari trampolines tipe 0/1/2” error runtime

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.

Setelah upgrade Xcode Unity iOS, runtime gagal dengan pesan "Anda menggunakan Unity iPhone Basic. Anda tidak diperbolehkan untuk menghapus layar percikan Unity dari permainan Anda”

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:

  • Ganti Proyek Xcode dari awal ketika bangunan dari Unity (ketidak menyetujuinya)
  • Hapus proyek yang sudah diinstal dari perangkat
  • Proyek bersih dalam Xcode (Artikel > Clean)
  • Hapus folder Data Derifd Xcode (Xcode > Preferences > Locations)

Jika ini masih tidak membantu mencoba menonaktifkan rekompresi PNG di Xcode:

  • Buka Proyek Xcode
  • Pilih proyek USB-Kabel project
  • Pilih tab Build Settings tab
  • Cari opsi Compress PNG files dan set ke NO

Unduhan www bekerja dengan baik di Editor Unity dan di Android, tetapi tidak di iOS

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.

"PlayerLoop disebut berulang!" kesalahan terjadi ketika menggunakan Cocoa melalui fungsi asli yang disebut dari skrip

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.

Profiler atau Debugger tidak bisa melihat permainan berjalan di perangkat iOS

  • Periksa bahwa Anda telah membangun build Pembangunan, dan memeriksa kotak WordPress.org dan Profiler Autoconnect (sesuai).
  • Aplikasi berjalan pada perangkat akan membuat siaran multicast ke 225.0.0.222 pada port UDP 54997. Periksa pengaturan jaringan Anda memungkinkan lalu lintas ini. Kemudian, profilerJendela yang membantu Anda untuk mengoptimalkan permainan Anda. Ini menunjukkan berapa banyak waktu yang dihabiskan di berbagai bidang permainan Anda. Sebagai contoh, dapat melaporkan persentase waktu yang dihabiskan rendering, aimating, atau dalam logika permainan Anda. More info
    Lihat di Glossary
    akan membuat koneksi ke perangkat jarak jauh pada port dalam kisaran 55000 - 55511 untuk mengambil data profiler dari perangkat. Port ini harus terbuka untuk akses TCP.

Missing DLLs

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.

Laporan konsol Debugger Xcode: EksekusiKecualian: Mencoba metode kompilasi JIT ‘(wrapper native-to-managed) Uji:TestFunc (int)’ saat berjalan dengan -aot-only

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);
    }
}

Xcode melempar kesalahan kompilasi: "ld : tidak dapat memasukkan pulau cabang. Tidak ada titik penyisipan yang tersedia. untuk arsitektur armv7", "clang: kesalahan: perintah linker gagal dengan kode keluar 1 (gunakan -v untuk melihat panggilan)"

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.


  • 2018–06–14 Login
API
Pelaporan kecelakaan bug di iOS