Belajar Unity: Inilah 5 Konsep Dasar Script C# Pada Unity! - IMedia9 - Connecting Inspiration

Breaking

Wednesday, October 10, 2018

Belajar Unity: Inilah 5 Konsep Dasar Script C# Pada Unity!



Pertanyaan yang paling sering muncul mengenai C# dan Unity adalah apa bedanya bahasa C# yang dipelajari di Visual Studio untuk pemrograman visual dengan bahasa C# yang dipelajari untuk pengembangan game di Unity? Bukankah bahasanya sama-sama C#?

Jawaban dari pertanyaan itu, yang rasanya pernah juga saya bahas di web ini tapi lupa, tetaplah sama. Bahasanya memang sama, yang beda adalah konteksnya. Analoginya begini, bayangkan jika ada seorang dokter berbicara dengan tukang printer. Mereka sama-sama berbicara dengan bahasa Indonesia dan yang diomongin adalah Infus.

Pertanyaannya adalah infus manakah yang dimaksud? Bukankah mereka berdua sama-sama ngomong pakai bahasa Indonesia?


Jadi nggak nyambung kan?

Begitulah kurang lebih kira-kira posisi bahasa C# di Visual Studio (sebagai pemrograman visual) dan Unity (yang menggunakan Editor Visual Studio). Secara umum bahasanya sama, yang diomongin itu-itu juga, syntaknya sama, tapi ketika konteksnya sudah berhubungan dengan game, maka C# versi VS akan "berbeda" dengan C# versi Unity.

Perbedaannya di mana saja? Yuk, kita simak satu per satu. Oh ya, sebelum lupa, bagi anda yang ingin memahami beberapa konsep fundamental dengan Unity, anda bisa membacanya di sini.

1. Apalah Artinya Sebuah Nama? Untuk Dipanggil!




Konsep utama dalam pemrograman C# adalah nama file harus sama dengan nama class. Jika anda gagal dalam mengimplementasikan hal yang super-simpel-bin-sederhana-dan-sangat-gampang ini, maka bersiap-siaplah untuk menerima error seperti ini.

Error sejuta umat yang bikin pemula pada nangis darah.


Penyebab dari error ini sangat simpel sebenarnya. Yaitu nama file yang anda buat tidak sama dengan nama class. Kronologis kejadian ini biasanya, setelah saya teliti dengan cara seksama dan tempo sesingkat-singkatnya, adalah:

1. Anda klik kanan pada panel Assets dan pilih Create > C# Script

2. Anda melihat tulisan NewBehaviorScript pada sebuah kotak edit kecil dan sedang dihighlight dengan warna biru. 

3. Anda bingung mau ngapain, terus anda KLIK SEMBARANG. (Ini masalahnya)

4. Kemudian TIBA-TIBA anda berubah pikiran, entah kesambet atau emang niat, pokoknya berubah pikiran aja. Anda klik lagi file tadi, dan tekan F2, terus anda ketikan: "HelloWorld" khas pemula.

5. Dan saat anda coba eksekusi Unity, anda pun error. Terus gugling sana sini, masuk keluar forum, dengan satu pertanyaan: "Maaf, saya newbie, ini errornya kenapa ya?"
    Saat anda melakukan KLIK SEMBARANG, anda telah menyimpan script tersebut dengan nama defaultnya yaitu NewBehaviorScript !

    Jika kemudian anda berubah pikiran dan ingin mengganti nama script dengan nama yang lebih pantas, ganti pulalah nama classnya.

    Rule #1: Nama file HARUS SAMA dengan nama class. 

    Jadi penyebab error itu terjadi karena nama file tidak sama dengan nama class. Solusinya? Samain lah! Pilih salah satu. Mau nama filenya yang diganti, atau nama classnya.


    2. Robot Yang Keren Pasti Punya Permen, Eh Komponen



    Script pada Unity hanya akan dieksekusi jika script tersebut telah menjadi Component untuk sebuah GameObject. Kenapa harus begitu? Meneketehe. Yang jelas konsep Unity ini "sangat berbeda" dengan konsep yang digunakan pada pemrograman visual lainnya.

    Jadi jika anda telah berhasil membuat sebuah file dan menjalankan Unity dengan klik tombol Play, bersiaplah bingung jika tidak ada apa pun yang terjadi.


    Rule #2: Script Unity HANYA DIEKSEKUSI jika telah menjadi Component. 

    Lalu bagaimana caranya membuat sebuah script menjadi komponen di Unity? Ada 2 Cara. Cara yang pertama adalah dengan menarik Script tersebut (drag-drop) langsung pada sebuah GameObject atau dengan klik pada tombol Add Component pada GameObject dan cari script yang dimaksud.




    3. Sekali Atau Untuk Selamanya



    Ketika saya pertama kali belajar Unity, ada satu hal yang membuat saya bingung. Kenapa di Script Unity hanya terdapat 2 fungsi yaitu Start() & Update()? Apa gunanya kedua fungsi tersebut? Karena penasaran saya pun melakukan percobaan.

    Percobaan #1: 

    Saya tulis perintah Debug.Log("Start: Hello World") di fungsi Start()

     void Start () {  
         Debug.Log("Start: Hello World");  
     }  
    

    Hasilnya adalah seperti berikut:


    Tulisan Start: Hello World ditulis sebanyak 1 kali. Sesuai dengan script!

    Percobaan #2: 

    Saya melakukan looping pada perintah Debug.Log("Start: Hello World") di fungsi Start() sebanyak 100 kali.

         void Start () {  
            for (int i=0; i<100; i++)  
            {  
              Debug.Log("Start: Hello World");  
            }  
         }  
    

    Hasilnya adalah seperti berikut:


    Tulisan Start: Hello World ditulis sebanyak 100 kali. Sesuai dengan looping pada script!

    Saya puas dengan hasilnya. Karena percobaan ini membuktikan satu hal jika fungsi Start() adalah fungsi yang dieksekusi pertama kali oleh Unity. Seperti fungsi Main() pada seluruh pemrograman yang bermazhab C.

    Percobaan #3: 

    Saya tulis perintah Debug.Log("Update: Hello World") di fungsi Update()

       void Update () {  
         Debug.Log("Start: Hello World");  
       }  
    

    Hasilnya adalah seperti berikut:


    Ini aneh! Padahal saya tidak melakukan looping di fungsi Update(). Tapi kenapa tulisannya muncul terus menerus? Dan bahkan loopingnya melampaui angka 100 yang saya set di fungsi Start.

    Para programmer yang lebih expert dan jago dari saya pasti akan langsung bilang:

    "Hei om Rickman yang cupu, fungsi Update Unity itu adalah fungsi yang dijalankan setiap frame secara terus menerus. Jadi semua perintah yang ditulis di fungsi Update akan dijalankan terus menerus sampai aplikasi Unity nya berhenti."

    Dan penjelasan itu bikin saya tambah bingung.



    Terus menerus? Lah itu kan artinya looping. Tapi di mana loopingnya? Saya nggak melihat fungsi for, while atau repeat di sana. Kalau mau looping mestinya perintahnya sama dengan yang saya tulis di Start().

    Pake for, while atau repeat barangkali.

    Tapi faktanya nggak. Bener yang dibilangin sama para master-master Unity di atas. Saya mempelajari Unity selama 9 tahun, dan sampai saat ini saya masih nggak ngerti di bagian mana Unity membuat fungsi Update bisa diloop setiap frame.

    Ajaib.

    Dan hal itu membuat saya lanjut ke percobaan selanjutnya.

    Percobaan #4: 

    Bagaimana jika saya tulis perintah loop di fungsi Update()?

       void Update () {  
         for (int i = 0; i < 100; i++)  
         {  
           Debug.Log("Update: Hello World");  
         }  
       }  
    

    Hasilnya adalah seperti berikut:


    Fungsi Update akan menyelesaikan loop-nya terlebih dahulu, lalu mengulangi lagi untuk frame selanjutnya dengan kecepatan tinggi. Incrementnya bertambah setiap kelipatan 100.

    Sampai sini kesimpulan yang bisa saya dapatkan adalah: Unity memiliki fungsi-fungsi khusus,  ~ yang sampai sekarang saya masih bingung gimana cara kerjanya ~ yang fungsi itu bisa dijalankan sekali atau untuk selamanya.

    Pertanyaan selanjutnya!

    Apakah hanya fungsi Start dan Update?

    Ternyata tidak.

    Percobaan #5: 

    Saya buat script berikut dengan penanda angka untuk lebih memahami cara kerja internal Unity terhadap fungsi-fungsi khususnya.

       void Awake()  
       {  
         Debug.Log("Awake: 1");  
       }  
       void Start () {  
         Debug.Log("Start: 2");  
          }  
          void Update () {  
         Debug.Log("Update: 3");  
       }  
       void FixedUpdate()  
       {  
         Debug.Log("Update: 4");  
       }  
       void LateUpdate()  
       {  
         Debug.Log("Update: 5");  
       }  
    

    Hasilnya adalah sebagai berikut:


    Melalui daftar tersebut anda bisa melihat jika fungsi Awake dijalankan pertama kali sebelum Start, dan fungsi FixedUpdate jalan terlebih dahulu, disusul Update dan LateUpdate. Kegunaan dari urutan fungsi ini sangat tergantung dari kompleksitas game yang akan anda bangun.

    Rule #3: Unity Punya Fungsi-Fungsi Khusus Yang Dieksekusi Secara Khusus Pula

    Satu percobaan terakhir dari fungsi ini adalah ketika saya non-aktifkan scriptnya.


    Anda masih ingat dengan kata-kata saya jika script pada Unity hanya akan berjalan jika dipasang pada GameObject? Syarat lainnya adalah script tersebut harus aktif. Jika tidak mana bisa jalan?

    Ternyata saya salah. Meski tidak diaktifkan, ternyata ada satu fungsi yang tetap dieksekusi meski script dalam keadaan tidak aktif.


    4.  Publik Figur Tidak Sama Dengan Les Privat



    Lupakan judulnya. Nggak nyambung kok. Saya hanya ingin anda fokus pada 2 kata saja yaitu Public dan Private. Dalam pemrogaman berorientasi objek, public diartikan sebagai keyword yang menunjuk pada variabel/fungsi yang bisa diakses oleh objek lain. Sementara private hanya bisa diakses oleh dirinya sendiri.

    Pada Unity, definisi itu mengalami sedikit penambahan, yaitu setiap variabel public bisa menjadi sebuah properti di Inspector yang nilainya bisa diutak-atik tanpa harus masuk kembali ke dalam codingan.

    Misalnya saya membuat 2 variabel berikut:

       private string Kalimat1;  
       public string Kalimat2;  
       // Use this for initialization  
       void Start () {  
         Debug.Log("Kalimat1 = " + Kalimat1);  
         Debug.Log("Kalimat2 = " + Kalimat2);  
       }  
    

    Maka hasilnya adalah sebagai berikut:


    Kok nggak ada isinya?

    Karena 2 variabel tersebut memang belum ada isinya.

    Yuk kita isi sekarang! Caranya?

    Untuk Kalimat2 (yang pakai keyword Public) bakalan muncul di Inspector, jadi bisa kita isi langsung.


    Untuk Kalimat1 nggak muncul di Inspector, jadi isinya mesti lewat coding.

       private string Kalimat1;  
       public string Kalimat2;  
       // Use this for initialization  
       void Start () {  
         Kalimat1 = "Ini kalimat1"; 
         Debug.Log("Kalimat1 = " + Kalimat1);  
         Debug.Log("Kalimat2 = " + Kalimat2);  
       }  
    


    Enakan mana?

    Bukan masalah enak nggak enak. Tapi menentukan variabel private dan public lebih tertuju kepada fungsi dari variabel itu sendiri. Apakah memang perlu diubah dari luar atau tidak?

    Apakah fungsi variabel public cuma itu?

    Nggak.

    Ada satu lagi.

    Konsep komunikasi antar-script via keyword public ini merupakan rahasia besar kekuatan Unity. Jika anda bisa memahaminya, maka 50% konsep dasar pemrograman Unity sudah anda kuasai.

    Cius?

    Kok anda gampang percaya sih? Kalau saya bohong gimana?



    Perhatikan skema berikut. Saya membuat 2 buah script yaitu HelloWorld.cs dan ScriptPemanggil.cs yang dipasangkan pada satu GameObject yang sama. ScriptPemanggil.cs akan menjalankan perintah untuk menuliskan kalimat dari HelloWorld.cs yang ditulis melalui Inspector.

    Apakah itu mungkin?


    Mungkin banget!

    Dalam kasus inilah konsep No 1 dan No 2 dipakai. Lupa? Baca lagi dari atas!

    Untuk memanggil fungsi dari script lain, maka langkah yang harus dilakukan adalah:


    Panggil Namanya 3 Kali...

    Panggil Namanya 3 Kali...

    Panggil Namanya 3 Kali...


    Nama siape yang tiga kali?


    1. Panggil Nama GameObject yang dipasangi script tersebut.

    2. Panggil Nama Script yang mau diakses.

    3. Panggil Nama variabel/metode yang mau mau diakses

    Pas kan? Tiga kali!



    Coba kita urut satu per satu.

    1. Panggil Nama GameObject yang dipasangi script tersebut.

    Karena nama GameObject yang dipasangi script adalah "GameObject" (nggak saya ganti karena males), jadi anda bisa gunakan fungsi:

    GameObject.Find("GameObject")

    2. Panggil Nama Script yang mau diakses.

    Untuk memanggil Script yang sudah menjadi permen, eh Component, anda perlu menggunakan fungsi GetComponent sehingga menjadi:

    GameObject.Find("GameObject").GetComponent()

    3. Panggil Nama variabel/metode yang mau mau diakses

    Untuk memanggil nama variabel.metode yang ada di dalam Component, anda tinggal panggil saja namanya. Perhatikan ini:


    Pada code completion di atas, hanya ada Kalimat2 yang muncul karena memang hanya variabel itu saja yang dicap sebagai public, bukan Kalimat1.

    Sudah paham?

    Coding lengkapnya seperti ini:

          void Start () {  
         Debug.Log(GameObject.Find("GameObject").GetComponent<HelloWorld>().Kalimat2);  
          }  
    

    Jika anda masih belum paham dengan maksud dari komunikasi antar-script dengan logika sederhana ini, (yang mungkin juga dikarenakan saya tidak pandai dalam menyampaikan sesuatu), maka saran saya carilah referensi sebanyak mungkin untuk dapat memahaminya.

    Rule #4: Pahami Teknik Pemanggilan GameObject dan Component

    Trust me!

    Jika anda nggak paham dengan analogi logika super simpel ini, anda akan mengalami banyak "kesulitan" untuk membuat game apa pun dengan Unity.

    Kenapa ini jadi penting?

    Karena dalam game akan banyak sekali terjadi komunikasi antar script? Pernah main Mobile Legends?



    Pernakah anda nge-kill karakter musuh? Anda mencet skill anda yang ada di script anda, tapi kenapa karakter musuh yang mati padahal dia dipasangi oleh script yang lain dan bukan script anda? Jadi sebenarnya anda manggil script anda untuk mengakses script musuh, atau musuh mengakses script anda kemudian script anda yang dipanggil dan script musuh jadi terpengaruh sehingga dia mati?



    Pusing kan?

    5. Mobil Apakah Yang Bisa Berubah Menjadi Robot?



    Transform merupakan kunci dari seluruh GameObject dasar pada Unity. Setidaknya ada 3 class penting dalam transform yaitu Position, Rotation dan Scale. Saat melakukan modifikasi terhadap salah satu atribut pada class-class tersebut, anda TIDAK BISA mengakses nilainya secara langsung.

    Perhatikan percobaan saya berikut ini.

       public Vector3 Koordinat;  
       // Use this for initialization  
       void Start () {  
         Koordinat = Vector3.zero;  
         Koordinat.x = Koordinat.x + 10;  
         Debug.Log(Koordinat);  
       }  
    

    Saya membuat sebuah variabel bertipe Vector3 (X,Y,Z), mengisinya dengan Vector.zero yang berarti (0,0,0) dan menambahkan koordinat X + 10 unit.

    Hasilnya? Seharusnya menjadi 10,0,0 bukan? Karena hanya koordinat X saja yang saya tambahkan. Perhatikan hasilnya:


    Benar! Berarti codingan saya nggak salah.

    Karena transform adalah bagian dari GameObject, jika saya modifikasi script ini untuk menggerakan sebuah kubus, harusnya tidak ada masalah bukan?

    Percobaan #1:

    Saya ingin membuat sebuah Cube yang semula ada di koordinat 0,0,0 bergerak sebanyak 10 unit ke sumbu X dengan cara yang sama.

    Perhatikan perintahnya:

       public Transform Kubus;  
       // Use this for initialization  
       void Start () {  
         Kubus.transform.position = Vector3.zero;  
         Kubus.transform.position.x = Kubus.transform.position.x + 10;  
         Debug.Log(Kubus.transform.position);  
       }  
    
    

    Codingan ini harusnya benar. Kan mirip! Tapi kok malah error?


    Errornya menyebutkan agar saya menyimpan nilai dalam variabel temporer terlebih dahulu. Kenapa mesti gitu?

    Ya udahlah. Saya nurut aja. Saya ganti codingannya jadi gini.

    Percobaan #2:

       // Use this for initialization  
       void Start () {  
         Kubus.transform.position = Vector3.zero;  
         Vector3 temp = Kubus.transform.position;  
         temp.x = temp.x + 10;  
         Kubus.transform.position = temp;  
         Debug.Log(Kubus.transform.position);  
       }  
    

    Jadi nggak error sih. Tapi saya masih nggak ngerti kenapa mesti begini? Ini seperti sebuah lari estafet yaitu ketika anda DILARANG untuk lari sendirian, dan harus menyerahkan tongkat pada teman anda untuk mencapai garis finish. Anda mungkin bisa ke garis finish sendirian, tapi ya itu, dilarang.



    Jadi jangan tanya saya kenapa Unity menggunakan konsep ini. Pokoknya gitu aja.

    Next? Apakah sudah selesai?

    Belum.

    Jika kita jalankan script ini maka akan muncul error lanjutan.


    Di sinilah konsep no 1 dan no 4 digunakan. Lupa? Baca lagi dari awal!

    Ketika anda membuat sebuah variabel public, maka variabel itu perlu diinisialisasi di luar codingan yaitu dari Inspector.

    Untuk kasus ini, karena ceritanya kita ingin menggerakan kubus tapi kubusnya nggak pernah ada jadi cukup tambahkan Cube. Dan isi sebagai parameter.


    Selesai. Semoga bermanfaat dan sampai jumpa di postingan saya selanjutnya.

    Tambahan:
    Jika anda seorang Game Developer atau Game Artist yang membutuhkan game assets gratis, saya sudah mengumpulkan beberapa di antaranya di sini. Semoga bermanfaat.



    1 comment:

    1. penjelasannya bagus disertai analogi yang bisa dipahami dengan mudah (ya ga semuanya mudah sih, ada pusingnya juga wkwk), lucu dan tidak membosankan, keep posting om !

      ReplyDelete