Unity menyediakan API scripting umum dan pengalaman di semua platform yang mendukungnya. Namun, beberapa platform memiliki batasan yang melekat. Untuk membantu Anda memahami pembatasan ini, tabel berikut menjelaskan pembatasan yang berlaku untuk setiap platform dan scripting backendKerangka kerja yang skrip di Unity. Unity mendukung tiga backend scripting yang berbeda tergantung pada platform target: Mono, .NET dan IL2CPP. Platform Windows Universal, namun hanya mendukung dua: .NET dan IL2CPP. More info
Lihat di Glossary:
Platform (scripting backend) | Ahead-of-time compile | No threads | .NET Core class libraries subset | |
---|---|---|---|---|
Android (IL2CPP) | ✔ | |||
Android (Mono) | ||||
iOS (IL2CPP) | ✔ | |||
Standalone (IL2CPP) | ✔ | |||
Standalone (Mono) | ||||
Universal Windows PlatformFitur IAP yang mendukung simulator Pembelian Aplikasi Microsoft, yang memungkinkan Anda untuk menguji aliran pembelian IAP pada perangkat sebelum menerbitkan aplikasi Anda. More info Lihat di Glossary (IL2CPP) |
✔ | |||
Platform Windows Universal (.NET) | ✔ | |||
WebGLLogin API yang membuat grafis 2D dan 3D di browser web. Opsi build Unity WebGL memungkinkan Unity untuk mempublikasikan konten sebagai program JavaScript yang menggunakan teknologi HTML5 dan WebGL rendering API untuk menjalankan konten Unity di browser web. More info Lihat di Glossary (IL2CPP) |
✔ | ✔ |
Beberapa platform tidak memungkinkan generasi kode runtime. Oleh karena itu, setiap kode terkelola yang tergantung pada kompilasi tepat waktu (JIT) pada perangkat target akan gagal. Sebagai gantinya, Anda harus mengkompilasi semua kode yang dikelola terlebih dahulu (AOT). Seringkali, perbedaan ini tidak masalah, tetapi dalam beberapa kasus tertentu, platform AOT memerlukan pertimbangan tambahan.
Platform AOT tidak dapat mengimplementasikan metode di ruang nama System.Reflection.Emit
. Sisa System.Reflection
diterima, selama kompiler dapat mengganggu bahwa kode yang digunakan melalui refleksi perlu ada di runtime.
Platform AOT mungkin menghadapi masalah dengan serialisasi dan deserialisasi karena penggunaan refleksi. Jika jenis atau metode hanya digunakan melalui refleksi sebagai bagian dari serialisasi atau deserialisasi, kompilator AOT tidak dapat mendeteksi bahwa perlu menghasilkan kebutuhan kode untuk jenis atau metode.
Jika Anda menggunakan metode generik, kompiler harus melakukan beberapa pekerjaan tambahan untuk memperluas kode tertulis Anda ke kode yang dieksekusi pada perangkat. Misalnya, Anda perlu kode yang berbeda untuk List
dengan int
atau double
. Jika Anda menggunakan metode virtual, di mana perilaku ditentukan pada runtime daripada waktu kompilasi, kompiler dapat dengan mudah memerlukan generasi kode runtime di tempat-tempat di mana tidak sepenuhnya jelas dari kode sumber.
Contoh kode berikut bekerja persis seperti yang diharapkan pada platform JIT (contohnya mencetak “nilai pengukuran: Nol” ke konsol sekali):
using UnityEngine;
using System;
public class AOTProblemExample : MonoBehaviour, IReceiver
{
public enum AnyEnum
{
Zero,
One,
}
void Start()
{
// Subtle trigger: The type of manager *must* be
// IManager, not Manager, to trigger the AOT problem.
IManager manager = new Manager();
manager.SendMessage(this, AnyEnum.Zero);
}
public void OnMessage<T>(T value)
{
Debug.LogFormat("Message value: {0}", value);
}
}
public class Manager : IManager
{
public void SendMessage<T>(IReceiver target, T value) {
target.OnMessage(value);
}
}
public interface IReceiver
{
void OnMessage<T>(T value);
}
public interface IManager
{
void SendMessage<T>(IReceiver target, T value);
}
Namun, ketika Anda mengeksekusi kode ini pada platform AOT dengan backend scripting IL2CPPBack-end scripting bersatu yang dapat Anda gunakan sebagai alternatif untuk Mono ketika proyek bangunan untuk beberapa platform. More info
Lihat di Glossary, pengecualian ini terjadi:
ExecutionEngineException: Attempting to call method 'AOTProblemExample::OnMessage<AOTProblemExample+AnyEnum>' for which no ahead of time (AOT) code was generated.
at Manager.SendMessage[T] (IReceiver target, .T value) [0x00000] in <filename unknown>:0
at AOTProblemExample.Start () [0x00000] in <filename unknown>:0
Demikian juga, backend skrip Mono memberikan pengecualian serupa ini:
ExecutionEngineException: Attempting to JIT compile method 'Manager:SendMessage<AOTProblemExample/AnyEnum> (IReceiver,AOTProblemExample/AnyEnum)' while running with --aot-only.
at AOTProblemExample.Start () [0x00000] in <filename unknown>:0
compiler AOT tidak mengenali bahwa harus menghasilkan kode untuk metode generik OnMessage
dengan T
AnyEnum
, sehingga terus, melewatkan metode ini. Ketika metode itu disebut, dan runtime tidak dapat menemukan kode yang tepat untuk dieksekusi, itu mengembalikan pesan kesalahan ini.
Untuk bekerja di sekitar masalah AOT seperti ini, Anda dapat memaksa kompiler untuk menghasilkan kode yang tepat. Untuk melakukan ini, tambahkan metode contoh berikut ke kelas AOTProblemExample
:
public void UsedOnlyForAOTCodeGeneration()
{
// IL2CPP needs only this line.
OnMessage(AnyEnum.Zero);
// Mono also needs this line. Note that we are
// calling directly on the Manager, not the IManager interface.
new Manager().SendMessage(null, AnyEnum.Zero);
// Include an exception so we can be sure to know if this method is ever called.
throw new InvalidOperationException("This method is used for AOT code generation only. Do not call it at runtime.");
}
Ketika kompilator menemukan panggilan eksplisit ke OnMessage
dengan T
AnyEnum
, itu menghasilkan kode yang tepat untuk runtime untuk dijalankan. Metode UsedOnlyForAOTCodeGeneration
tidak perlu disebut; itu hanya perlu ada untuk kompiler untuk mengenalinya.
Metode yang terkelola yang perlu dihadirkan ke pointer fungsi C sehingga mereka dapat dipanggil dari kode asli memiliki beberapa pembatasan pada platform AOT:
[MonoPInvokeCallback]
attributeBeberapa platform tidak mendukung penggunaan benang, sehingga setiap kode yang berhasil yang menggunakan namespace System.Threading
gagal pada runtime. Juga, beberapa bagian perpustakaan kelas .NET tidak bergantung pada benang. Contoh yang sering digunakan adalah kelas System.Timers.Timer
, yang tergantung pada dukungan untuk benang.
IL2CPP tidak mendukung filter pengecualian C#. Anda harus memodifikasi kode yang tergantung pada filter pengecualian ke blok catch
yang tepat.
IL2CPP tidak mendukung tipe System.TypedReference
atau kata kunci __makeref
C#.
IL2CPP tidak mendukung refleksi atribut MarhsalAs
dan FieldOffset
pada runtime. Ini tidak mendukung atribut ini pada waktu kompilasi. Anda harus menggunakan ini untuk WordPress.org yang tepat.
IL2CPP tidak mendukung kata kunci C# dynamic
. Kata kunci ini membutuhkan kompilasi JIT, yang tidak mungkin dengan IL2CPP.
IL2CPP tidak mendukung metode API Marshal.Prelink
atau Marshal.PrelinkAll
.