Dalam versi baru
unity pada 2018, mereka akhirnya secara resmi menambahkan
sistem komponen Entity baru
, atau
ECS singkatnya, yang memungkinkan Anda untuk hanya bekerja dengan data mereka alih-alih pekerjaan biasa dengan komponen objek.
Sistem tugas tambahan menawarkan Anda untuk menggunakan daya komputasi paralel untuk meningkatkan kinerja kode Anda.
Bersama-sama, kedua sistem baru ini (
ECS dan
Sistem Pekerjaan ) menawarkan tingkat pemrosesan data yang baru.
Khususnya, dalam artikel ini saya tidak akan menganalisis seluruh sistem
ECS , yang saat ini tersedia sebagai seperangkat alat yang dapat diunduh secara terpisah dalam
kesatuan , tetapi hanya akan mempertimbangkan sistem tugas dan bagaimana hal itu dapat digunakan di luar paket
ECS .
Sistem baru
Awalnya,
persatuan digunakan untuk dapat menggunakan komputasi multi-threaded, tetapi semua ini harus dibuat oleh pengembang sendiri, untuk menyelesaikan masalah sendiri dan untuk mengatasi perangkap. Dan jika sebelumnya perlu untuk bekerja secara langsung dengan hal-hal seperti membuat utas, menutup utas, sinkronisasi, sekarang semua pekerjaan ini jatuh di pundak mesin, dan pengembang sendiri hanya perlu membuat tugas dan menyelesaikannya.
Tugasnya
Untuk melakukan perhitungan dalam sistem baru, perlu untuk menggunakan tugas yang merupakan objek yang terdiri dari metode dan data untuk perhitungan.
Seperti data lainnya dalam sistem
ECS , tugas dalam
Sistem Pekerjaan juga direpresentasikan sebagai struktur yang mewarisi salah satu dari tiga antarmuka.
Ijob
Antarmuka tugas paling sederhana yang berisi satu metode
Jalankan yang tidak mengambil apa pun dalam bentuk parameter dan tidak mengembalikan apa pun.
Tugas itu sendiri terlihat seperti ini:
Ijobpublic struct JobStruct : IJob { public void Execute() {} }
Dalam metode
Jalankan , Anda dapat melakukan perhitungan yang diperlukan.
IJobParallelFor
Antarmuka lain dengan metode
Jalankan yang sama, yang pada gilirannya sudah menerima
indeks parameter numerik.
IJobParallelFor public struct JobStruct : IJobParallelFor { public void Execute(int index) {} }
Antarmuka
IJobParallelFor ini, tidak seperti antarmuka
IJob , menawarkan untuk mengeksekusi tugas beberapa kali dan tidak hanya mengeksekusi, tetapi memecah eksekusi ini menjadi blok yang akan didistribusikan di antara utas.
Tidak jelas Jangan khawatir tentang ini, saya akan memberi tahu Anda lebih banyak.IJobParallelForTransform
Dan antarmuka khusus terakhir, yang, seperti namanya, dirancang untuk bekerja dengan transformasi objek. Ini juga berisi metode
Execute , dengan
indeks parameter numerik dan parameter
TransformAccess di mana posisi, ukuran dan rotasi transformasi berada.
IJobParallelForTransform public struct JobStruct : IJobParallelForTransform { public void Execute(int index, TransformAccess transform) {} }
Karena kenyataan bahwa Anda tidak dapat bekerja dengan objek
kesatuan secara langsung dalam tugas, antarmuka ini hanya dapat memproses transformasi data sebagai struktur
TransformAccess yang terpisah.
Selesai, sekarang Anda tahu bagaimana struktur tugas dibuat, Anda dapat melanjutkan untuk berlatih.
Penyelesaian tugas
Mari kita membuat tugas sederhana yang diwarisi dari antarmuka
IJob dan menyelesaikannya. Untuk ini, kita memerlukan skrip
MonoBehaviour sederhana dan struktur tugas itu sendiri.
Testjob public class TestJob : MonoBehaviour { void Start() {} }
Sekarang letakkan skrip ini pada beberapa objek di tempat kejadian. Dalam skrip yang sama (
TestJob ) di bawah ini kami akan menulis struktur tugas dan jangan lupa untuk mengimpor perpustakaan yang diperlukan.
Pekerjaan sederhana using Unity.Jobs; public struct SimpleJob : IJob { public void Execute() { Debug.Log("Hello parallel world!"); } }
Dalam metode
Execute , misalnya, cetak garis sederhana ke konsol.
Sekarang mari kita beralih ke metode
Mulai skrip
TestJob , di mana kita akan membuat turunan tugas dan kemudian menjalankannya.
Testjob public class TestJob : MonoBehaviour { void Start() { SimpleJob job = new SimpleJob(); job.Schedule().Complete(); } }
Jika Anda melakukan semuanya seperti pada contoh, maka setelah memulai gim Anda akan mendapatkan pesan sederhana ke konsol seperti pada gambar.

Apa yang terjadi di sini: setelah memanggil metode
Jadwal , penjadwal menempatkan tugas di pegangan dan sekarang dapat diselesaikan dengan memanggil metode
Lengkap .
Ini adalah contoh tugas yang hanya mencetak teks ke konsol. Untuk tugas untuk melakukan komputasi paralel apa pun, perlu mengisinya dengan data.
Data dalam tugas
Seperti dalam sistem
ECS , dalam tugas tidak ada akses ke objek
kesatuan , Anda tidak bisa memasukkan
GameObject ke dalam tugas dan mengubah namanya di sana. Yang dapat Anda lakukan adalah mentransfer beberapa parameter objek terpisah ke tugas, mengubah parameter ini, dan setelah menyelesaikan tugas, menerapkan perubahan ini kembali ke objek.
Ada beberapa batasan untuk data dalam tugas itu sendiri: pertama, itu harus struktur, dan kedua, itu
tidak boleh tipe data yang dapat
dikonversi , yaitu, Anda tidak bisa meneruskan
boolean atau
string yang sama ke tugas.
Pekerjaan sederhana public struct SimpleJob : IJob { public float a, b; public void Execute() { float result = a + b; Debug.Log(result); } }
Dan kondisi utama: data yang tidak tertutup dalam wadah hanya dapat diakses di dalam tugas!
Wadah
Saat bekerja dengan komputasi multi-utas, ada kebutuhan untuk bertukar data antar utas. Agar dapat mentransfer data ke dalamnya dan membacanya kembali di sistem tugas, untuk tujuan ini ada wadah. Wadah-wadah ini disajikan dalam bentuk struktur biasa dan saya bekerja berdasarkan prinsip jembatan yang dengannya data dasar disinkronkan di antara aliran.
Ada beberapa jenis wadah:
NativeArray . Jenis wadah yang paling sederhana dan paling sering digunakan disajikan sebagai array sederhana dengan ukuran tetap.
NativeSlice . Wadah lain - array, seperti yang jelas dari terjemahan, dirancang untuk memotong NativeArray menjadi beberapa bagian.
Ini adalah dua wadah utama yang tersedia tanpa menghubungkan sistem
ECS . Dalam versi yang lebih maju, ada beberapa jenis wadah.
NativeList . Ini adalah daftar data reguler.
NativeHashMap . Analog kamus dengan kunci dan nilai.
NativeMultiHashMap .
NativeHashMap yang sama dengan hanya beberapa nilai di bawah satu kunci.
NativeQueue Daftar antrian data.
Karena kita bekerja tanpa menghubungkan sistem
ECS , hanya
NativeArray dan
NativeSlice yang tersedia untuk
kita .
Sebelum melanjutkan ke bagian praktis, perlu untuk menganalisis poin yang paling penting - penciptaan instance.
Buat Kontainer
Seperti yang saya katakan sebelumnya, kontainer ini mewakili jembatan di mana data disinkronkan di antara utas. Sistem tugas membuka jembatan ini sebelum mulai bekerja dan menutupnya setelah selesai. Proses pembukaan disebut "
alokasi " (
Alokasi ) atau
"alokasi memori" , proses penutupan disebut "
pelepasan sumber daya " (
Buang ).
Alokasi inilah yang menentukan berapa lama tugas dapat menggunakan data dalam wadah - dengan kata lain, berapa lama jembatan akan terbuka.
Untuk lebih memahami kedua proses ini, mari kita lihat gambar di bawah ini.

Bagian bawah menunjukkan siklus hidup utas utama (utas
utama ), yang dihitung dalam jumlah frame, pada frame pertama, kami membuat utas paralel lain (
utas baru) yang ada untuk sejumlah frame tertentu dan kemudian ditutup dengan aman.
Di
utas baru yang sama tugas dengan wadah tiba.
Sekarang lihat bagian atas gambar.
Alokasi bilah putih menunjukkan masa pakai wadah. Dalam bingkai pertama, wadah
dialokasikan - jembatan dibuka, sampai saat ini wadah tidak ada, setelah semua perhitungan dalam tugas selesai, wadah dibebaskan dari memori dan pada frame ke-9 jembatan ditutup.
Juga pada strip ini (
Alokasi ) ada segmen waktu (
Temp ,
TempJob dan
Presistent ), masing-masing segmen ini menunjukkan perkiraan masa pakai wadah.
Mengapa segmen ini diperlukan !? Faktanya adalah bahwa eksekusi suatu tugas berdasarkan durasi dapat berbeda, kita dapat mengeksekusinya secara langsung dalam metode yang sama dengan yang kita buat, atau kita dapat memperpanjang waktu eksekusi tugas jika cukup rumit, dan segmen-segmen ini menunjukkan seberapa mendesak dan berapa lama tugas dapat menggunakan data dalam wadah.
Jika masih belum jelas, saya akan menganalisis setiap jenis alokasi menggunakan contoh.Sekarang kita dapat beralih ke bagian praktis membuat wadah, untuk ini kita kembali ke metode
Mulai skrip
TestJob dan membuat contoh baru wadah
NativeArray dan jangan lupa untuk menghubungkan perpustakaan yang diperlukan.
Temp
Testjob using Unity.Jobs; using Unity.Collections; public class TestJob : MonoBehaviour { void Start() { NativeArray<int> array = new NativeArray<int>(10, Allocator.Temp); } }
Untuk membuat instance wadah baru, Anda harus menentukan ukuran dan jenis alokasi dalam konstruktornya. Contoh ini menggunakan tipe
Temp , karena tugas akan dilakukan hanya dalam metode
Mulai .
Sekarang inisialisasi variabel array yang sama persis dalam struktur tugas
SimpleJob .
Pekerjaan sederhana public struct SimpleJob : IJob { public NativeArray<int> array; public void Execute() {} }
Selesai Sekarang Anda dapat membuat tugas itu sendiri dan mengirimkan contoh array ke sana.
Mulai void Start() { NativeArray<int> array = new NativeArray<int>(10, Allocator.Temp); SimpleJob job = new SimpleJob(); job.array = array; }
Untuk menjalankan tugas kali ini, kami akan menggunakan pegangan
JobHandle untuk mendapatkannya dengan memanggil metode
Jadwal yang sama.
Mulai void Start() { NativeArray<int> array = new NativeArray<int>(10, Allocator.Temp); SimpleJob job = new SimpleJob(); job.array = array; JobHandle handle = job.Schedule(); }
Sekarang Anda dapat memanggil metode
Lengkap pada pegangannya dan memeriksa apakah tugas tersebut selesai untuk menampilkan teks di konsol.
Mulai void Start() { NativeArray<int> array = new NativeArray<int>(10, Allocator.Temp); SimpleJob job = new SimpleJob(); job.array = array; JobHandle handle = job.Schedule(); handle.Complete(); if (handle.IsCompleted) print(" "); }
Jika Anda menjalankan tugas dalam formulir ini, maka setelah memulai permainan Anda akan mendapatkan kesalahan merah besar yang mengatakan bahwa Anda tidak melepaskan wadah array dari sumber setelah tugas selesai.
Sesuatu seperti itu.

Untuk menghindarinya, panggil metode
Buang di wadah setelah menyelesaikan tugas.
Mulai void Start() { NativeArray<int> array = new NativeArray<int>(10, Allocator.Temp); SimpleJob job = new SimpleJob(); job.array = array; JobHandle handle = job.Schedule(); handle.Complete(); if (handle.IsCompleted) print("Complete"); array.Dispose(); }
Maka Anda dapat memulai kembali dengan aman.
Tetapi tugas itu tidak melakukan apa-apa! - lalu tambahkan beberapa tindakan untuk itu.
Pekerjaan sederhana public struct SimpleJob : IJob { public NativeArray<int> array; public void Execute() { for(int i = 0; i < array.Length; i++) { array[i] = i * i; } } }
Dalam metode
Execute , saya mengalikan indeks setiap elemen array sendiri dan menulisnya kembali ke array
array untuk mencetak hasilnya ke konsol dalam metode
Start .
Mulai void Start() { NativeArray<int> array = new NativeArray<int>(10, Allocator.Temp); SimpleJob job = new SimpleJob(); job.array = array; JobHandle handle = job.Schedule(); handle.Complete(); if (handle.IsCompleted) print(job.array[job.array.Length - 1]); array.Dispose(); }
Apa yang akan menjadi hasil di konsol jika kita mencetak elemen terakhir dari kuadrat?
Ini adalah bagaimana Anda dapat membuat wadah, menaruhnya dalam tugas dan melakukan tindakan pada wadah tersebut.
Ini adalah contoh menggunakan tipe alokasi
Temp , yang menyiratkan menyelesaikan tugas dalam satu bingkai. Jenis ini paling baik digunakan ketika Anda perlu melakukan perhitungan dengan cepat tanpa memuat utas utama, tetapi Anda harus berhati-hati jika tugasnya terlalu rumit atau jika akan ada banyak, kendur dapat terjadi, dalam hal ini lebih baik menggunakan jenis
TempJob, yang akan saya analisis nanti.
Tempjob
Dalam contoh ini, saya akan sedikit
mengubah struktur tugas
SimpleJob dan mewarisinya dari antarmuka
IJobParallelFor lainnya.
Pekerjaan sederhana public struct SimpleJob : IJobParallelFor { public NativeArray<Vector2> array; public void Execute(int index) {} }
Juga, karena tugas akan berjalan lebih lama dari satu bingkai, kami akan mengeksekusi dan mengumpulkan hasil tugas dalam berbagai metode
Sedar dan
Mulai yang disajikan dalam bentuk coroutine. Untuk melakukan ini, ubah penampilan kelas
TestJob sedikit .
Testjob public class TestJob : MonoBehaviour { private NativeArray<Vector2> array; private JobHandle handle; void Awake() {} IEnumerator Start() {} }
Dalam metode
Sedarlah , kita akan membuat tugas dan wadah vektor, dan dalam metode
Mulai , output data yang diterima dan sumber daya rilis.
Bangun void Awake() { this.array = new NativeArray<Vector2>(100, Allocator.TempJob); SimpleJob job = new SimpleJob(); job.array = this.array; }
Di sini sekali lagi, wadah
array dibuat dengan jenis alokasi
TempJob , setelah itu kami membuat tugas dan menanganinya dengan memanggil metode
Jadwal dengan perubahan kecil.
Bangun void Awake() { this.array = new NativeArray<Vector2>(100, Allocator.TempJob); SimpleJob job = new SimpleJob(); job.array = this.array; this.handle = job.Schedule(100, 5) }
Parameter pertama dalam metode
Jadwal menunjukkan berapa kali tugas akan dieksekusi, berikut adalah jumlah yang sama dengan ukuran array
array .
Parameter kedua menunjukkan berapa banyak blok untuk berbagi tugas.
Blok apa lagi?Sebelumnya, untuk menyelesaikan tugas, utas hanya memanggil metode
Eksekusi sekali, sekarang perlu memanggil metode ini 100 kali, sehingga penjadwal membagi 100 kali repetisi ini ke dalam blok yang didistribusikan di antara utas agar tidak memuat utas terpisah. Dalam contoh, seratus pengulangan akan dibagi menjadi 5 blok, masing-masing 20 pengulangan, yaitu, penjadwal mungkin akan mendistribusikan 5 blok ini ke dalam 5 utas, di mana setiap utas akan memanggil metode
Jalankan 20 kali. Dalam praktiknya, tentu saja, bukan fakta bahwa penjadwal akan melakukan hal itu, semuanya tergantung pada beban kerja sistem, jadi mungkin semua 100 pengulangan akan terjadi dalam satu utas.
Sekarang Anda dapat memanggil metode
Lengkap pada gagang tugas.
Bangun void Awake() { this.array = new NativeArray<Vector2>(100, Allocator.TempJob); SimpleJob job = new SimpleJob(); job.array = this.array; this.handle = job.Schedule(100, 5); this.handle.Complete(); }
Di
Mulai coroutine, kami akan memeriksa pelaksanaan tugas dan kemudian kami akan membersihkan wadah.
Mulai IEnumerator Start() { while(this.handle.isCompleted == false){ yield return new WaitForEndOfFrame(); } this.array.Dispose(); }
Sekarang mari kita beralih ke tindakan dalam tugas itu sendiri.
Pekerjaan sederhana public struct SimpleJob : IJobParallelFor { public NativeArray<Vector2> array; public void Execute(int index) { float x = index; float y = index; Vector2 vector = new Vector2(x * x, y * y / (y * 2)); this.array[index] = vector; } }
Setelah menyelesaikan tugas dalam metode
Mulai , tampilkan semua elemen array di konsol.
Mulai IEnumerator Start() { while(this.handle.IsCompleted == false){ yield return new WaitForEndOfFrame(); } foreach(Vector2 vector in this.array) { print(vector); } this.array.Dispose(); }
Selesai, Anda bisa berlari dan melihat hasilnya.
Untuk memahami perbedaan antara
IJob dan
IJobParallelFor, lihat gambar di bawah ini.
Sebagai contoh,
IJob juga dapat menggunakan loop sederhana
untuk melakukan perhitungan beberapa kali, tetapi dalam kasus apa pun, utas hanya dapat memanggil metode
Jalankan sekali selama seluruh durasi tugas - ini adalah cara membuat satu orang melakukan ratusan tindakan yang sama secara berturut-turut.
IJobParallelFor menawarkan tidak hanya untuk mengeksekusi tugas dalam satu utas beberapa kali, tetapi juga untuk mendistribusikan repetisi ini di antara utas lainnya.

Secara umum, jenis alokasi
TempJob sangat cocok untuk sebagian besar tugas yang dilakukan pada beberapa bingkai.
Tetapi bagaimana jika Anda perlu menyimpan data bahkan setelah menyelesaikan tugas, bagaimana jika setelah menerima hasil Anda tidak perlu menghancurkannya segera. Untuk ini, perlu menggunakan jenis alokasi
Persistent , yang menyiratkan pelepasan sumber daya kemudian "
bila perlu!" .
Gigih
Mari kita kembali ke kelas
TestJob dan mengubahnya. Sekarang kita akan membuat tugas dalam metode
OnEnable , memeriksa pelaksanaannya dalam metode
Pembaruan dan membersihkan sumber daya dalam metode
OnDisable .
Dalam contoh, kita akan memindahkan objek dalam metode
Pembaruan , untuk menghitung lintasan kita akan menggunakan dua wadah vektor -
inputArray di mana kita akan meletakkan posisi saat ini dan
outputArray dari mana kita akan menerima hasilnya.
Testjob public class TestJob : MonoBehaviour { private NativeArray<Vector2> inputArray; private NativeArray<Vector2> outputArray; private JobHandle handle; void OnEnable() {} void Update() {} void OnDisable() {} }
Kami juga
akan sedikit
memodifikasi struktur tugas
SimpleJob dengan mewarisinya dari antarmuka
IJob untuk menjalankannya sekali.
Pekerjaan sederhana public struct SimpleJob : IJob { public void Execute() {} }
Dalam tugas itu sendiri, kita juga akan mengkhianati dua wadah vektor, satu vektor posisi dan delta numerik, yang akan memindahkan objek ke target.
Pekerjaan sederhana public struct SimpleJob : IJob { [ReadOnly] public NativeArray<Vector2> inputArray; [WriteOnly] public NativeArray<Vector2> outputArray; public Vector2 position; public float delta; public void Execute() {} }
Atribut
ReadOnly dan
WriteOnly menunjukkan batasan aliran pada tindakan yang terkait dengan data di dalam wadah.
ReadOnly menawarkan stream hanya untuk membaca data dari container, atribut
WriteOnly , sebaliknya, memungkinkan stream untuk hanya menulis data ke container. Jika Anda perlu melakukan dua tindakan ini sekaligus dengan satu wadah, maka Anda tidak perlu menandainya dengan atribut sama sekali.
Mari kita
beralih ke metode
OnEnable dari kelas
TestJob di mana kontainer akan diinisialisasi.
Dapat dipertahankan void OnEnable() { this.inputArray = new NativeArray<Vector2>(1, Allocator.Persistent); this.outputArray = new NativeArray<Vector2>(1, Allocator.Persistent); }
Dimensi wadah akan tunggal karena perlu untuk mengirim dan menerima parameter hanya sekali. Jenis alokasi akan
Persisten .
Dalam metode
OnDisable ,
kami akan merilis sumber daya wadah.
Dapat ditolak void OnDisable() { this.inputArray.Dispose(); this.outputArray.Dispose(); }
Mari kita buat metode
CreateJob terpisah di mana kita akan membuat tugas dengan pegangannya dan di sana kita akan mengisinya dengan data.
Buat Pekerjaan void CreateJob() { SimpleJob job = new SimpleJob(); job.delta = Time.deltaTime; Vector2 position = this.transform.position; job.position = position; Vector2 newPosition = position + Vector2.right; this.inputArray[0] = newPosition; job.inputArray = this.inputArray; job.outputArray = this.outputArray; this.handle = job.Schedule(); this.handle.Complete(); }
Sebenarnya, inputArray tidak benar-benar diperlukan di sini, karena dimungkinkan untuk mentransfer vektor arah hanya ke tugas, tetapi saya pikir akan lebih baik untuk memahami mengapa atribut ReadOnly dan WriteOnly ini diperlukan sama sekali.Dalam metode
Pembaruan , kami akan memeriksa apakah tugas sudah selesai, setelah itu kami menerapkan hasil yang diperoleh ke objek mengubah dan menjalankannya lagi.
Perbarui void Update() { if (this.handle.IsCompleted) { Vector2 newPosition = this.outputArray[0]; this.transform.position = newPosition; CreateJob(); } }
Sebelum memulai, kita akan sedikit mengubah metode
OnEnable sehingga tugas dibuat segera setelah wadah diinisialisasi.
Dapat dipertahankan void OnEnable() { this.inputArray = new NativeArray<Vector2>(1, Allocator.Persistent); this.outputArray = new NativeArray<Vector2>(1, Allocator.Persistent); CreateJob(); }
Selesai, sekarang Anda bisa pergi ke tugas itu sendiri dan melakukan perhitungan yang diperlukan dalam metode
Execute .
Jalankan public void Execute() { Vector2 newPosition = this.inputArray[0]; newPosition = Vector2.Lerp(this.position, newPosition, this.delta); this.outputArray[0] = newPosition; }
Untuk melihat hasil kerja, Anda bisa melempar skrip
TestJob pada beberapa objek dan menjalankan game.
Sebagai contoh, sprite saya secara bertahap bergeser ke kanan.
Secara umum, jenis alokasi
Persistent sangat bagus untuk wadah yang dapat digunakan kembali yang tidak perlu dihancurkan dan dibuat ulang setiap saat.
Jadi tipe apa yang digunakan !?Tipe
Temp paling baik digunakan untuk melakukan perhitungan dengan cepat, tetapi jika tugasnya terlalu kompleks dan besar, slack dapat terjadi.
Tipe
TempJob sangat bagus untuk bekerja dengan objek
kesatuan , jadi Anda bisa mengubah parameter objek dan menerapkannya, misalnya, di bingkai berikutnya.
Jenis
Persistent dapat digunakan ketika kecepatan tidak penting bagi Anda, tetapi Anda hanya perlu terus-menerus menghitung beberapa jenis data di samping, misalnya, memproses data melalui jaringan, atau pekerjaan AI.
Tidak Valid dan Tidak AdaAda dua jenis alokasi yang tidak valid dan Tidak Ada , tetapi mereka lebih dibutuhkan untuk debugging, dan tidak berpartisipasi dalam pekerjaan.
Penanganan pekerjaan
Secara terpisah, ada baiknya untuk menganalisis kemampuan dari tugas menangani, karena selain memeriksa proses pelaksanaan tugas, pegangan kecil ini masih dapat membuat seluruh jaringan tugas melalui dependensi (meskipun saya lebih suka menyebutnya antrian lebih).
Misalnya, jika Anda perlu melakukan dua tugas dalam urutan tertentu, maka untuk ini Anda hanya perlu melampirkan gagang satu tugas ke gagang yang lain.
Itu terlihat seperti ini.

Setiap individu menangani awalnya berisi tugasnya sendiri, tetapi ketika digabungkan, kami mendapatkan pegangan baru dengan dua tugas.
Mulai void Start() { Job jobA = new Job(); JobHandle handleA = jobA.Schedule(); Job jobB = new Job(); JobHandle handleB = jobB.Schedule(); JobHandle result = JobHandle.CombineDependecies(handleA, handleB); result.Complete(); }
Atau begitulah.
Mulai void Start() { JobHandle handle; for(int i = 0; i < 10; i++) { Job job = new Job(); handle = job.Schedule(handle); } handle.Complete(); }
Urutan eksekusi disimpan dan penjadwal tidak akan memulai tugas berikutnya sampai yakin dengan yang sebelumnya, tetapi penting untuk diingat bahwa properti
pegangan IsCompleted akan menunggu semua tugas di dalamnya untuk menyelesaikan.
Kesimpulan
Wadah
- Saat bekerja dengan data dalam wadah, jangan lupa bahwa ini adalah struktur, jadi setiap penimpaan data dalam wadah tidak mengubahnya, tetapi membuatnya lagi.
- Apa yang terjadi jika Anda mengatur jenis alokasi Temp dan tidak menghapus sumber daya setelah tugas selesai? Kesalahannya.
- Bisakah saya membuat wadah sendiri? Ada kemungkinan bahwa persatuan tersebut menjelaskan secara terperinci proses pembuatan wadah khusus di sini, tetapi lebih baik untuk berpikir beberapa kali: apakah itu layak, mungkin akan ada cukup wadah biasa!?
Keamanan!
Data statis.Jangan mencoba menggunakan data statis dalam suatu tugas ( Acak dan lain-lain), akses apa pun ke data statis akan melanggar keamanan sistem. Sebenarnya, saat ini Anda dapat mengakses data statis, tetapi hanya jika Anda yakin mereka tidak berubah selama pekerjaan - yaitu, mereka benar-benar statis dan hanya-baca.Kapan harus menggunakan sistem tugas?Semua contoh yang diberikan di sini dalam artikel ini hanya bersyarat, dan menunjukkan cara bekerja dengan sistem ini, dan bukan kapan menggunakannya. Sistem tugas dapat digunakan tanpa ECS,Anda perlu memahami bahwa sistem juga menghabiskan sumber daya di tempat kerja dan bahwa untuk alasan apa pun segera menulis tugas, membuat tumpukan kontainer tidak ada gunanya - semuanya akan menjadi lebih buruk. Misalnya, menghitung ulang larik dengan ukuran 10 ribu elemen tidak akan benar - ini akan membutuhkan lebih banyak waktu untuk penjadwal untuk bekerja, tetapi menghitung ulang semua poligon terran besar atau bahkan menghasilkannya adalah solusi yang tepat, Anda dapat memecah terran menjadi tugas dan memproses masing-masing dalam aliran terpisah.Secara umum, jika Anda terus-menerus terlibat dalam perhitungan kompleks dalam proyek dan terus-menerus mencari peluang baru untuk membuat proses ini kurang intensif sumber daya, maka Sistem Pekerjaaninilah yang Anda butuhkan. Jika Anda terus-menerus bekerja dengan perhitungan kompleks yang tidak dapat dipisahkan dari objek dan ingin kode Anda bekerja lebih cepat dan didukung pada sebagian besar platform, maka ECS pasti akan membantu Anda dengan ini. Jika Anda membuat proyek hanya untuk WebGL maka ini bukan untuk Anda, saat ini Sistem Pekerjaan tidak mendukung bekerja di browser, meskipun ini bukan masalah untuk unitecs, tetapi untuk pengembang browser itu sendiri.Sumber dengan semua contoh