Pointer di C # Unity

8

Hei, saya baru saja belajar tentang pointer baru-baru ini dan bertanya-tanya bagaimana saya bisa menggunakannya dalam c # (saya baru belajar tentang mereka di c ++) dalam kesatuan. Saya punya beberapa pertanyaan.

  1. Pointer menggunakan pemrograman tingkat rendah untuk menemukan posisi nilai yang berbeda di komputer, jadi apakah itu berarti Anda hanya dapat mengakses nilai variabel dari skrip apa pun?
  2. Jika demikian, bagaimana saya memanggil lokasi variabel hanya dengan kode lokasinya?
  3. Apakah ada perbedaan nyata antara pointer dalam C # dan C ++ yang harus saya ketahui?
  4. Bagaimana saya bisa menggunakan pointer dengan tipe variabel di Unity (Vector3s, Transforms, GameObjects, dll ...)?

Ada begitu banyak pertanyaan lagi yang mungkin harus dan ingin saya tanyakan jika Anda memiliki info atau sumber tambahan.

Ryan Henry
sumber

Jawaban:

6

Secara umum untuk C # dan khusus untuk Unity saya akan menyarankan untuk tidak ... tetapi jika Anda benar-benar ingin, atau punya alasan yang baik, Anda bisa.

Dalam C # Anda perlu membiasakan diri dengan apa yang disebut kode tidak aman . Takut belum?

Di Unity Anda harus mengaktifkan mode kompilasi yang tidak aman sehingga Anda tidak akan dapat menggunakan pemutar web jika Anda merencanakannya. Anda dapat membaca lebih lanjut di sini atau di sini .

Jadi pada dasarnya C # dirancang dengan Kolektor Sampah karena banyak bahasa scripting. Gagasan umum adalah untuk mencoba dan abstrak gagasan manajemen memori untuk menyederhanakan pengembangan. Anda masih dapat berakhir dengan kebocoran sumber daya jika Anda tidak membatalkan objek Anda. Sejujurnya saya bukan pendukung GC yang besar dan lebih suka metode RAII , tetapi ini adalah dunia tempat kita hidup.

Sebagian besar pengembang C ++ juga akan setuju bahwa Anda tidak boleh menggunakan pointer secara langsung dan harus memilih untuk menggunakan tipe yang dirancang RAII alias smart pointer . Jika Anda berada di tanah C maka kemungkinan pointer adalah sifat kedua bagi Anda, tetapi meskipun demikian itu membantu untuk mengabstraksikan mereka sampai taraf tertentu.

Jika Anda menggunakannya dalam C # hanya perlu diketahui bahwa ada potensi yang sangat nyata Anda dapat menambahkan kerentanan keamanan atau benar-benar jahat dan sulit untuk melacak bug. Anda juga perlu mengingat bahwa Anda harus berhati-hati untuk tidak merujuk objek yang dapat dipindahkan oleh GC. Perhatikan penggunaan pernyataan tetap di sini .

Anda juga dapat menggunakan Pointer di Unity dengan menulis plugin asli . Ini lagi akan mengesampingkan build webplayer, tetapi fitur HTML5 baru bekerja berdasarkan emscripten jadi jika Anda berencana menggunakan itu Anda mungkin bisa jika Anda berhati-hati. Plugin asli memungkinkan Anda untuk memperluas Unity pada basis per platform. Saya menulis plugin asli untuk berkomunikasi dengan beberapa mikrokontroler melalui koneksi serial misalnya.

Jadi untuk meringkas Anda harus bertanya pada diri sendiri mengapa saya ingin menggunakan pointer di C # di Unity. Jika Anda hanya ingin melakukannya untuk bersenang-senang ... Hancurkan diri Anda.

Sunting: Saya minta maaf jika saya telah menyinggung siapa pun karena saya tahu pikiran saya tentang GC bukan pendapat populer saat ini.

Jika Anda benar-benar membaca jawaban saya, Anda akan perhatikan bahwa saya tidak menyebut C # bahasa scripting. Saya membandingkannya dengan "banyak bahasa scripting", namun, dalam konteks Unity sangat banyak digunakan sebagai bahasa scripting. Ini semacam DSL untuk Unity jika Anda mau. Sering kali Anda akan melihatnya bahkan disebut sebagai Unity Script dalam konteks ini (ini sebagian besar mengacu pada alternatif Javascript Unity untuk C #). Jika Anda memasukkan LLVM ke dalam pipeline, Anda bisa langsung mengkompilasinya ke kode asli untuk platform ... lalu apa yang akan Anda sebut itu? Jadi saya benar-benar tidak ingin membelah rambut di sini.

Banyak referensi bagus untuk rekayasa perangkat lunak diisi dengan pendapat:

Efektif C ++ , Lebih Efektif C ++ , C ++ FAQ , Efektif C # , Desain C ++ Modern , Pola Desain ... Dan yang lainnya yang tak terhitung jumlahnya. Saya tidak merasa ini membuat argumen menjadi kurang kredibel jika mereka diikuti oleh penjelasan yang bijaksana.

Saya tidak benar-benar habis-habisan mengatakan "Jangan pernah gunakan pointer !!" . Bahkan saya masih menggunakannya telanjang pada kesempatan. Saya mengatakan "secara umum" seperti pada "lebih suka menggunakan kode aman ke kode tidak aman di C #". Ada situasi di mana itu bisa bermanfaat, dan itu adalah salah satu fitur yang sangat kuat dari C # untuk memilih dan memilih alat Anda. C # bahkan memungkinkan Anda untuk memiliki transparansi dalam proses GC sampai tingkat tertentu, bahasa seperti Dart tidak dan dapat menyebabkan kebocoran sumber daya dengan sangat mudah. Tentu jika Anda adalah satu-satunya pengembang proyek kecil itu tidak akan menjadi masalah. Jika Anda berada di tim katakan 10+ dengan ratusan ribu baris kode maka itu bisa rumit.

Saya hanya ingin pembaca untuk berhati-hati ketika menggunakan pointer telanjang. Ini sama saja dengan mengatakan sangat berhati-hati ketika bekerja dengan listrik utama. Saya tidak mengatakan jangan menjadi tukang listrik, hanya saja jika Anda melakukan kesalahan dan tidak memperlakukannya dengan hormat Anda sudah mati.

Saya suka contoh yang diberikan oleh Lasse di mana kinerja mungkin telah mendikte kebutuhan.

Matthew Sanders
sumber
1
C # bukan bahasa scripting, meskipun bisa digunakan untuk itu. Java juga memiliki GC dan itu bukan bahasa scripting. Menjawab dengan pendapat Anda sendiri apa yang terbaik secara umum, bukan jawaban objektif yang kami cari di situs ini. Untuk tujuan tertentu, sesuatu seperti kode dan pointer yang tidak aman bisa sangat efisien.
Lasse
1
Saya tidak mengerti mengapa jawaban ini diturunkan - sangat informatif dan menunjukkan banyak penelitian / pengetahuan dan tautan ke bacaan lebih lanjut. Khusus untuk @Lasse apa itu bahasa scripting? Tentu saja akan lebih tepat untuk mengatakan "bahasa yang digunakan untuk scripting dalam persatuan", tetapi saya tidak melihat banyak alasan untuk downvote karena Matius menghilangkan 7 kata yang jelas dan menggunakan satu (lebih) istilah yang disederhanakan.
keajaiban
@wondra Saya tidak memilih karena jawabannya tidak membuatnya jelas bahwa ada tempat di mana pointer dapat digunakan dengan sangat baik di C #. Itu semua tergantung pada platform tujuan dan target. Sebenarnya jawabannya adalah mencoba menakut-nakuti semua orang menggunakan pointer.
Lasse
1
@wondra Jawaban ini hampir tidak menjawab pertanyaan. Yang dilakukannya adalah mengatakan untuk tidak menggunakan pointer. Bagian komentar ini bukan tempat yang tepat untuk membahas hal ini. Anda dapat bergabung dengan obrolan jika Anda merasa memiliki lebih banyak argumen.
Lasse
1
@Lasse tidak dapat meyakinkan Anda dan ini bukan pertarungan saya, tetapi melihat jawaban Anda - Anda menulis persis sama dengan jawaban ini (yang diposting lebih cepat), apalagi Anda hanya menyertakan subset (= informasi kurang) pada topik seperti jawaban ini.
wonderra
6

C # menggunakan referensi untuk membagikan objek yang bukan tipe nilai . Ini berarti bahwa semuanya biasanya dilewatkan dengan referensi. Jika Anda ingin memberikan tipe nilai dengan referensi, Anda dapat menggunakan kata kunci ref . Perbedaan dari tipe referensi dan tipe-nilai adalah bahwa tergantung pada seberapa besar tipe-nilai itu, biasanya membutuhkan lebih banyak memori yang disalin ketika diteruskan ke suatu fungsi. Referensi hanya 32 bit atau 64 bit , atau 4 byte atau 8 byte. Anda bisa mendapatkan lebih banyak kinerja dari kode Anda dalam loop yang sangat ketat jika Anda menggunakan referensi alih-alih hanya menyalin semua data yang berisi variabel-variabel yang diketik nilai, dengan asumsi mereka lebih besar dari 4 atau 8 byte.

Misalnya pada Persatuan objek MonoBehaviour (kelas) apa pun adalah tipe referensi, dan objek Vector3 (struct) apa pun adalah tipe-Nilai.

Ada juga blok kode yang tidak aman yang memungkinkan Anda mengetik kode yang memungkinkan Anda membuat dan memodifikasi data secara tidak aman. Untuk menggunakan kode yang tidak aman, Anda harus mengatur kompiler untuk mengizinkan kode yang tidak aman. Pointer dapat digunakan dengan cara ini. Dengan menggunakan kode yang tidak aman, cek tertentu tidak digunakan yang ada di sana dengan kode aman, yang membuat kode tidak aman lebih sulit untuk ditulis tanpa kesalahan. Ada beberapa tempat yang dapat memanfaatkan kode tidak aman di C #. On Unity, kode yang tidak aman tidak didukung di semua platform. Biasanya menggunakan referensi alih-alih pointer yang tidak aman sudah cukup ketika bekerja dengan Unity.

Berikut adalah contoh ( sumber ) penggunaan pointer kode tidak aman di C # dengan Unity:

public static class Rope
{
    // C# function declaration to match C++
    [DllImport(SlingshotImport.c_libName)]
    static unsafe extern void UpdateRopeParticlesUnsafe(
        Vector3* oldNew,
        Vector3* curr,
        int numParticles);

    // C# wrapper function for Unity C# script
    static void UpdateRopeParticles(
        Vector3[] oldNew,
        Vector3[] curr,
        int numParticles)
    {
        unsafe
        {
            fixed (Vector3* oldNewPtr = oldNew)
            fixed (Vector3* currPtr = curr)
            {
                UpdateRopeParticlesUnsafe(oldNewPtr, currPtr, numParticles);
            }
        }
    }
}
Lasse
sumber
Saya merasa menarik bahwa Anda mengkritik jawaban saya dan menggunakan argumen yang sama, minus info relevan lainnya, dan hanya menyertakan diskusi singkat tentang tipe nilai vs referensi. Anda setidaknya dapat menyebutkan Boxing , optimasi JIT yang kadang-kadang dapat menghapus jenis salin overhead, cara menghindari tidak aman dengan menyusun , atau mungkin bahwa kode tidak aman tidak selalu lebih cepat dan aman
Matthew Sanders
Maaf jika Anda merasa diserang atau tersinggung. Itu bukan niat saya. Saya mengkritik jawaban Anda karena menurut saya itu sangat berdasarkan opini dan bukan berdasarkan fakta. Saya memberikan jawaban untuk pertanyaan yang diajukan bersama dengan beberapa contoh kode. Dari jawaban Anda, saya tidak dapat memahami hal-hal yang saya jelaskan dalam jawaban saya, yang saya rasa lebih relevan dengan pertanyaan yang diajukan. Saya tidak melihat bagaimana GC ada hubungannya dengan "bagaimana cara saya menggunakan pointer?" atau saya tidak melihat Anda menyebutkan bagaimana referensi bekerja pada C # karena pertanyaannya tampaknya menganggap variabel bekerja dengan cara yang sama dalam C # dan C ++.
Lasse
1
Jangan khawatir. Terima kasih atas permintaan maaf Anda. Saya menyebutkan GC karena Anda perlu menyadari bahwa melewati pointer ke tipe yang dikelola dapat menyebabkan masalah jika GC tiba-tiba memindahkan objek. Saya berasumsi pembaca mengetahui sistem tipe C # dan bagaimana referensi vs tipe nilai digunakan.
Matthew Sanders
Kalian benar-benar membuat sulit untuk menerima jawaban. Anda berdua memberi saya banyak informasi yang diperlukan sehingga saya akan memilih Anda berdua dan akan menerima yang datang terlebih dahulu. Saya tidak bermaksud apa-apa dengan itu. Saya hanya kesulitan memilih dan untuk menakut-nakuti saya dari "kode tidak aman" jangan khawatir. Saya tidak pernah menjadi orang yang mundur dari tantangan. Meskipun sekarang saya tahu bahwa bekerja dengan pointer tidak praktis karena berkaitan dengan pengembangan multi platform. Saya ingin mengucapkan terima kasih atas waktu dan pendapat Anda. dan saya minta maaf saya mulai WWIII tidak bermaksud melakukan itu.
Ryan Henry