◀ KEMBALI KE DAFTAR MODUL
Modul Pembelajaran Unity • C# • REST API

Membangun Simple Leaderboard di Unity

Belajar mengambil data peringkat dari server, menampilkannya pada Scroll View yang memanjang ke bawah, dan mengirim skor pemain baru menggunakan HTTP GET dan POST.

UnityWebRequestJSONTextMeshProScroll View

1. Tujuan Pembelajaran

Setelah menyelesaikan modul ini, peserta didik mampu:

  1. Memahami konsep dasar API, RESTful API, dan protokol HTTP dalam ekosistem game development.
  2. Membuat script pengantar menggunakan UnityWebRequest untuk menguji request GET dan POST dengan output pada tab Console Unity.
  3. Memahami arsitektur komunikasi data antara Unity Game Client dengan Web Server.
  4. Mengambil data leaderboard dari server menggunakan HTTP GET dan UnityWebRequest.
  5. Mengubah (deserialisasi) teks format JSON menjadi objek C# menggunakan model class.
  6. Membuat baris antarmuka (UI) secara dinamis pada Scroll View vertikal di Unity.
  7. Mengirimkan (serialisasi) nama dan skor pemain baru ke server menggunakan HTTP POST.
  8. Menerapkan alur refresh data secara otomatis setelah data baru berhasil dikirim.
Hasil akhir: peserta didik memahami konsep dasar komunikasi web, berhasil menguji request GET & POST melalui Console, serta membangun sistem leaderboard global interaktif berbasis Canvas UI di Unity.

2. Konsep Dasar API dan REST API

A. Apa itu API (Application Programming Interface)?

Secara sederhana, API (Application Programming Interface) adalah antarmuka atau jembatan penghubung yang memungkinkan dua sistem perangkat lunak yang berbeda untuk saling berkomunikasi, bertukar data, dan bekerja sama tanpa harus mengetahui detail teknis internal masing-masing.

🍽️ Analogi Dunia Nyata: Pelayan di Restoran
Bayangkan Anda sedang makan di sebuah restoran:
  • Tamu (Pelanggan) = Unity Game (Client): Anda ingin memesan makanan tertentu yang tercantum pada menu.
  • Pelayan = API: Mencatat pesanan Anda, membawanya ke dapur, menunggu masakan siap, lalu mengantarkan makanan yang sudah jadi kembali ke meja Anda. Anda tidak perlu tahu cara kerja kompor atau resep rahasia di dapur.
  • Dapur & Gudang = Web Server & Database: Tempat penyimpanan bahan mentah dan pengolahan data yang memasak pesanan sesuai permintaan.
🎮Unity ClientKirim Request (Permintaan)
➔
🌐APIJembatan Komunikasi
➔
🗄️Server & DatabaseSimpan & Olah Data

B. Apa itu REST API (RESTful API)?

REST (Representational State Transfer) adalah standar arsitektur komunikasi web yang paling luas digunakan di dunia. REST API bekerja di atas protokol standar internet, yaitu HTTP / HTTPS—protokol yang sama seperti saat kita berselancar di web browser.

Karakteristik penting dalam arsitektur REST API:

  • Client-Server: Game Unity (Client) berfokus pada grafis, input kontroler, dan gameplay, sedangkan Server berfokus pada penyimpanan data terpusat dan validasi keamanan. Keduanya independen.
  • Stateless: Setiap request yang dikirimkan oleh Unity harus mandiri dan membawa semua data yang dibutuhkan. Server tidak menyimpan riwayat percakapan sebelumnya antar-request.
  • Resource-Based: Setiap informasi di server diperlakukan sebagai sebuah sumber daya (resource) yang memiliki alamat unik bernama Endpoint / URL (contoh: /simple-leaderboard).
  • Format Standar (JSON): Pertukaran informasi dilakukan dalam format teks JSON yang terstruktur dan hemat ukuran bandwidth.

C. 4 Metode Utama HTTP (HTTP Verbs / Methods)

Ketika Unity berkomunikasi dengan REST API, Unity menentukan jenis tindakan yang diinginkan menggunakan HTTP Method (identik dengan operasi CRUD di basis data):

GET Mengambil / Membaca Data (Read)

Meminta data dari server tanpa mengubah apapun di database. Contoh: Mengambil 10 daftar skor teratas untuk ditampilkan pada layar game.

POST Mengirim Data Baru (Create)

Mengirim data baru dari game ke server untuk disimpan ke dalam database. Contoh: Mengirim nama pemain dan skor akhir saat Game Over.

PUT / PATCH Memperbarui Data (Update)

Mengubah atau memperbarui data yang sudah ada di server. Contoh: Mengganti nama akun atau memperbarui pengaturan profil pemain.

DELETE Menghapus Data (Delete)

Menghapus data tertentu dari server. Contoh: Mereset skor musim lalu atau menghapus riwayat permainan.

D. Mengenal HTTP Status Code (Kode Respon Server)

Server akan selalu membalas setiap request dengan kode status numerik 3-digit untuk memberitahukan status permintaan:

KodeNama StatusKategoriArti dalam Game
200OK2xx (Sukses)Permintaan berhasil dan server mengembalikan data (misal: sukses GET leaderboard).
201Created2xx (Sukses)Data baru berhasil dibuat dan disimpan di server (misal: sukses POST skor baru).
400Bad Request4xx (Client Error)Format data yang dikirim game salah (misal: nama kosong atau nilai non-angka).
404Not Found4xx (Client Error)Alamat endpoint salah atau resource yang dicari tidak ada di server.
500Internal Server Error5xx (Server Error)Terjadi kesalahan atau crash di sisi server backend.

E. Anatomi Format JSON

JSON (JavaScript Object Notation) adalah format teks ringkas untuk merepresentasikan struktur data. Unity memiliki library bawaan JsonUtility untuk mengubah objek C# menjadi JSON (serialization) dan sebaliknya (deserialization).

  • Object { }: Kumpulan data pasangan "key": value. Contoh: {"nama": "Budi", "nilai": 950}.
  • Array [ ]: Kumpulan daftar item berturut-turut. Contoh: [10, 20, 30] atau daftar data pemain.
  • Tipe data valid: String (teks bertanda kutip), Number (angka), Boolean (true/false), Array, Object, dan null.

F. Mengapa Game Memerlukan REST API?

🌍 Leaderboard Lintas Platform

Pemain di PC, Android, iOS, maupun WebGL dapat bersaing di satu papan peringkat global yang sama secara realtime.

🛡️ Keamanan & Integritas Data

Skor tersimpan di server aman, bukan di penyimpanan lokal perangkat (PlayerPrefs) yang rawan dimodifikasi atau dicurangi pemain.

⚡ Konten Dinamis Tanpa Update

Daftar event khusus, pesan pengumuman, atau hadiah harian dapat diperbarui dari server tanpa pemain harus download update aplikasi baru.

🔄 Komunikasi Asinkron (Anti-Lag)

Melalui UnityWebRequest dan Coroutine (IEnumerator), proses unduh/unggah berjalan di latar belakang sehingga gameplay tidak patah-patah.

3. Latihan 1: Mengambil Data (HTTP GET di Console)

A. Apa itu UnityWebRequest & Mengapa Harus Asinkron?

Di Unity, seluruh komunikasi pertukaran data melalui internet ditangani oleh class UnityWebRequest yang terdapat di dalam namespace UnityEngine.Networking.

⏳ Mengapa Komunikasi Web Harus Menggunakan Coroutine (Asinkron)?
Ketika game meminta data ke server melalui internet, diperlukan waktu sekian milidetik hingga detik (tergantung koneksi). Jika dipanggil secara biasa (sinkron/blocking), seluruh proses rendering Unity akan langsung membeku (freeze / hang) menunggu respon server.

Oleh karena itu, di Unity kita wajib menggunakan Coroutine (IEnumerator) dan kata kunci yield return request.SendWebRequest();. Unity akan mengirim request ke latar belakang (background thread), sementara gameplay tetap berjalan mulus di 60 FPS. Script baru akan melanjutkan eksekusi setelah server selesai merespons!

B. Endpoint API yang Digunakan

Untuk latihan GET ini, kita menggunakan REST API online dengan parameter limit untuk mengambil 3 data skor teratas:

FungsiHTTP MethodEndpoint URLKeterangan
Mengambil DataGEThttps://simple-api.appocket.id/simple-leaderboard?limit=3Mengambil 3 data skor teratas dari server.

C. Script C#: LatihanGetConsole.cs

Pada latihan ini, kita membuat script sederhana untuk meminta data ke server dan mencetak isi data mentah (raw JSON) langsung ke tab Console Unity tanpa perlu membuat antarmuka UI terlebih dahulu.

Buat file C# baru di folder Assets/Scripts dengan nama LatihanGetConsole.cs:

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class LatihanGetConsole : MonoBehaviour
{
    // Endpoint API leaderboard (dibatasi 3 data untuk pengujian)
    private string url = "https://simple-api.appocket.id/simple-leaderboard?limit=3";

    void Start()
    {
        Debug.Log("--- Memulai Latihan HTTP GET ---");
        StartCoroutine(GetDataFromServer());
    }

    IEnumerator GetDataFromServer()
    {
        Debug.Log("Mengirim request GET ke: " + url);

        // 1. Buat request GET menggunakan helper bawaan UnityWebRequest.Get
        using (UnityWebRequest request = UnityWebRequest.Get(url))
        {
            // 2. Kirim request secara asinkron dan tunggu hingga server membalas
            yield return request.SendWebRequest();

            // 3. Periksa apakah terjadi error jaringan / protokol
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("[GET ERROR] Gagal mengambil data: " + request.error);
                Debug.LogError("HTTP Status Code: " + request.responseCode);
            }
            else
            {
                // 4. Jika berhasil, tampilkan status code dan isi teks JSON mentah
                Debug.Log("[GET SUKSES] Data berhasil diterima dari server!");
                Debug.Log("HTTP Status Code: " + request.responseCode);

                string jsonHasil = request.downloadHandler.text;
                Debug.Log("Isi Data JSON dari Server:
" + jsonHasil);
            }
        }
    }
}

Langkah Pengujian Latihan GET di Unity:

  1. Di panel Hierarchy Unity, klik kanan lalu pilih Create Empty. Beri nama objek: Test_GET.
  2. Seret file script LatihanGetConsole.cs ke objek Test_GET di Hierarchy atau melalui tombol Add Component.
  3. Buka panel Console Unity (menu Window → General → Console atau tekan Ctrl + Shift + C).
  4. Tekan tombol Play ▶ di Unity Editor.

Simulasi Hasil Output pada Tab Console:

🎮 UNITY CONSOLE — HTTP GET OUTPUT
[Console] --- Memulai Latihan HTTP GET ---
[Console] Mengirim request GET ke: https://simple-api.appocket.id/simple-leaderboard?limit=3
[Console] [GET SUKSES] Data berhasil diterima dari server!
[Console] HTTP Status Code: 200
[Console] Isi Data JSON dari Server:
{"status":"success","total":2,"data":[{"rank":1,"id":1,"nama":"Budi Santoso","nilai":950,"created_at":"2026-10-15 11:19:05"},{"rank":2,"id":2,"nama":"Siti Rahma","nilai":880,"created_at":"2026-10-15 11:19:05"}]}
Analisis Hasil GET: Perhatikan teks JSON yang tercetak di Console! Anda dapat melihat properti "status": "success", jumlah "total", dan daftar array "data" yang memuat nama pemain, nilai, dan tanggal submit.

4. Latihan 2: Mengirim Data Skor (POST via WWWForm)

A. Apa itu WWWForm & Mengapa Digunakan?

Pada metode POST, game kita mengirimkan data baru ke server untuk disimpan ke database. Cara termudah dan paling ramah pemula di Unity adalah menggunakan class WWWForm.

METODE FORM-DATA Karakteristik WWWForm
  • Bekerja seperti formulir HTML web konvensional (pasangan key-value).
  • Menggunakan fungsi bawaan form.AddField("nama", nama) dan form.AddField("nilai", skor).
  • Unity otomatis mengatur header Content-Type: multipart/form-data dan pengatur upload tanpa perlu konversi byte manual.
  • Kompatibel langsung dengan backend PHP standar (dapat dibaca via $_POST['nama']).

B. Endpoint API yang Digunakan

FungsiHTTP MethodEndpoint URLKeterangan
Kirim Skor FormPOSThttps://simple-api.appocket.id/simple-leaderboardMengirim parameter nama dan nilai via Form-Data.

C. Script C#: LatihanPostWWWFormConsole.cs

Buat file C# baru di folder Assets/Scripts dengan nama LatihanPostWWWFormConsole.cs:

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class LatihanPostWWWFormConsole : MonoBehaviour
{
    // Endpoint API untuk mengirim skor
    private string url = "https://simple-api.appocket.id/simple-leaderboard";

    [Header("Data Skor Baru (Form Data)")]
    public string namaPemain = "Siswa SMK Telkom (Form)";
    public int skorPemain = 890;

    void Start()
    {
        Debug.Log("--- Memulai Latihan HTTP POST via WWWForm ---");
        StartCoroutine(KirimSkorDenganForm(namaPemain, skorPemain));
    }

    IEnumerator KirimSkorDenganForm(string nama, int skor)
    {
        Debug.Log("Menyiapkan WWWForm untuk: " + nama + " (" + skor + ")");

        // 1. Buat instance WWWForm dan tambahkan pasangan key-value
        WWWForm form = new WWWForm();
        form.AddField("nama", nama);
        form.AddField("nilai", skor);

        // 2. Gunakan UnityWebRequest.Post bawaan Unity yang otomatis mengurus payload & header
        using (UnityWebRequest request = UnityWebRequest.Post(url, form))
        {
            request.SetRequestHeader("Accept", "application/json");

            // 3. Kirim request secara asinkron dan tunggu respon server
            yield return request.SendWebRequest();

            // 4. Periksa status pengiriman
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("[WWWForm ERROR] Gagal mengirim data: " + request.error);
                Debug.LogError("HTTP Status Code: " + request.responseCode);
                Debug.LogError("Pesan Error Server: " + request.downloadHandler.text);
            }
            else
            {
                Debug.Log("[WWWForm SUKSES] Skor berhasil disimpan ke database server!");
                Debug.Log("HTTP Status Code: " + request.responseCode);
                Debug.Log("Balasan dari Server:
" + request.downloadHandler.text);
            }
        }
    }
}

Langkah Pengujian Latihan POST WWWForm di Unity:

  1. Nonaktifkan GameObject Test_GET di Hierarchy (hilangkan centang aktif di Inspector).
  2. Buat GameObject kosong baru: Test_POST_Form, lalu pasang script LatihanPostWWWFormConsole.cs.
  3. Di Inspector, Anda dapat mengubah Nama Pemain dan Skor Pemain.
  4. Tekan tombol Play ▶ di Unity Editor dan perhatikan tab Console.

Simulasi Hasil Output pada Tab Console:

🎮 UNITY CONSOLE — HTTP POST WWWFORM OUTPUT
[Console] --- Memulai Latihan HTTP POST via WWWForm ---
[Console] Menyiapkan WWWForm untuk: Siswa SMK Telkom (Form) (890)
[Console] [WWWForm SUKSES] Skor berhasil disimpan ke database server!
[Console] HTTP Status Code: 200
[Console] Balasan dari Server:
{"status":"success","message":"Data skor berhasil disimpan ke leaderboard.","data":{"id":8,"nama":"Siswa SMK Telkom (Form)","nilai":890,"rank":6}}

5. Latihan 3: Mengirim Data Skor (POST via JSON Payload)

A. Apa itu Payload JSON & Mengapa Digunakan di REST API Modern?

Selain form data, standar industri web modern paling luas menggunakan format JSON (JavaScript Object Notation) untuk body request POST. Format ini sangat digemari karena mendukung struktur data kompleks (nested objects, array, data bertingkat).

METODE JSON BODY Alur Pengiriman JSON di Unity:
  1. Menyusun teks JSON: {"nama": "Budi", "nilai": 950}.
  2. Mengonversi teks ke deretan byte array UTF-8: Encoding.UTF8.GetBytes(json).
  3. Memasang UploadHandlerRaw (pengirim byte) dan DownloadHandlerBuffer (penerima respon).
  4. Menetapkan header eksplisit: request.SetRequestHeader("Content-Type", "application/json").

B. Script C#: LatihanPostJsonConsole.cs

Buat file C# baru di folder Assets/Scripts dengan nama LatihanPostJsonConsole.cs:

using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

public class LatihanPostJsonConsole : MonoBehaviour
{
    // Endpoint API untuk mengirim skor
    private string url = "https://simple-api.appocket.id/simple-leaderboard";

    [Header("Data Skor Baru (JSON)")]
    public string namaPemain = "Siswa SMK Telkom (JSON)";
    public int skorPemain = 950;

    void Start()
    {
        Debug.Log("--- Memulai Latihan HTTP POST via JSON Payload ---");
        StartCoroutine(KirimSkorDenganJSON(namaPemain, skorPemain));
    }

    IEnumerator KirimSkorDenganJSON(string nama, int skor)
    {
        Debug.Log("Menyiapkan payload JSON untuk: " + nama + " (" + skor + ")");

        // 1. Susun string format JSON sesuai format API
        string jsonPayload = "{\"nama\":\"" + nama + "\",\"nilai\":" + skor + "}";
        Debug.Log("Payload String: " + jsonPayload);

        // 2. Ubah string JSON menjadi byte array UTF-8
        byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonPayload);

        // 3. Buat UnityWebRequest dengan UploadHandlerRaw
        using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
        {
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = new DownloadHandlerBuffer();

            // Set Header agar server mengenali format JSON
            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("Accept", "application/json");

            // 4. Kirim request secara asinkron
            yield return request.SendWebRequest();

            // 5. Periksa status pengiriman
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("[JSON ERROR] Gagal mengirim data: " + request.error);
                Debug.LogError("HTTP Status Code: " + request.responseCode);
                Debug.LogError("Pesan Error Server: " + request.downloadHandler.text);
            }
            else
            {
                Debug.Log("[JSON SUKSES] Skor berhasil disimpan ke database server!");
                Debug.Log("HTTP Status Code: " + request.responseCode);
                Debug.Log("Balasan dari Server:
" + request.downloadHandler.text);
            }
        }
    }
}

Langkah Pengujian Latihan POST JSON di Unity:

  1. Nonaktifkan GameObject Test_POST_Form di Hierarchy.
  2. Buat GameObject kosong baru: Test_POST_JSON, lalu pasang script LatihanPostJsonConsole.cs.
  3. Di Inspector, ubah Nama Pemain dan Skor Pemain sesuai keinginan Anda.
  4. Tekan tombol Play ▶ di Unity Editor dan perhatikan tab Console.

Simulasi Hasil Output pada Tab Console:

🎮 UNITY CONSOLE — HTTP POST JSON OUTPUT
[Console] --- Memulai Latihan HTTP POST via JSON Payload ---
[Console] Menyiapkan payload JSON untuk: Siswa SMK Telkom (JSON) (950)
[Console] Payload String: {"nama":"Siswa SMK Telkom (JSON)","nilai":950}
[Console] [JSON SUKSES] Skor berhasil disimpan ke database server!
[Console] HTTP Status Code: 200
[Console] Balasan dari Server:
{"status":"success","message":"Data skor berhasil disimpan ke leaderboard.","data":{"id":9,"nama":"Siswa SMK Telkom (JSON)","nilai":950,"rank":6}}

C. Pembuktian Alur Lengkap: Kirim Skor lalu Cek di GET

🎯 Uji Validasi Dua Arah:
  1. Setelah berhasil menjalankan LatihanPostJsonConsole.cs dan mendapat respon sukses 200, matikan Play Mode di Unity.
  2. Nonaktifkan objek Test_POST_JSON, lalu aktifkan kembali objek Test_GET.
  3. Tekan tombol Play Mode lagi.
  4. Perhatikan data JSON yang diterima pada script GET: Nama dan nilai yang baru saja Anda kirimkan kini telah tercatat secara online di database server!

D. Mengapa Sekarang Kita Perlu Membuat Leaderboard UI?

Dari ketiga latihan console di atas, kita telah menguasai komunikasi dasar Unity dengan web server: kita bisa mengambil data (GET), mengirim skor via Form (POST WWWForm), dan mengirim skor via JSON (POST JSON).

Namun, dalam game yang sebenarnya, pemain game tidak akan pernah membuka tab Console Unity! Pemain membutuhkan antarmuka grafis (UI) yang interaktif: papan peringkat berurut dengan medali, Scroll View yang bisa digulir ke bawah, input nama, dan tombol submit yang menarik.

🎮Game ClientInput nama & skor pemain
↔
🌐UnityWebRequestKirim / Ambil Data JSON
↔
🏆Canvas UI & Scroll ViewTampilan grafis interaktif

Pada bab-bab selanjutnya, kita akan mulai merancang antarmuka UI Canvas, mengonversi JSON mentah menjadi objek C# menggunakan serialization, dan menghubungkan script API dengan komponen UI di Unity!

6. Membuat UI di Unity

A. Buat objek UI

  1. Buat Canvas melalui GameObject → UI → Canvas.
  2. Pastikan tersedia EventSystem. Unity biasanya membuatnya otomatis saat UI dibuat.
  3. Di dalam Canvas, buat Scroll View, dua TextMeshPro Input Field, dua tombol, dan satu teks status.
  4. Tambahkan judul menggunakan TextMeshPro, misalnya “LEADERBOARD”.
Canvas ├── TitleText ├── Scroll View │ └── Viewport │ └── Content ├── NamaInput (TMP_InputField) ├── NilaiInput (TMP_InputField) ├── KirimButton ├── RefreshButton └── StatusText

B. Atur Content agar bisa scroll ke bawah

Pilih objek Content di dalam Scroll View, lalu tambahkan komponen berikut:

  • Vertical Layout Group: Child Alignment = Upper Center; Spacing = 8; Control Child Size Width dan Height aktif; Child Force Expand Width aktif dan Height nonaktif.
  • Content Size Fitter: Horizontal Fit = Unconstrained; Vertical Fit = Preferred Size.

Pada objek Scroll View, pastikan Scroll Rect mengarah ke Content. Pada Viewport, gunakan Rect Mask 2D. Aktifkan gerakan vertikal sesuai kebutuhan.

C. Buat prefab baris leaderboard

  1. Buat UI Panel bernama LeaderboardItem dengan tinggi kira-kira 60 px.
  2. Di dalamnya, buat empat teks TextMeshPro: RankText, NamaText, NilaiText, dan TanggalText.
  3. Susun teks secara horizontal dengan Horizontal Layout Group atau atur posisi secara manual.
  4. Seret objek dari Hierarchy ke folder Assets/Prefabs untuk membuat prefab.
  5. Hapus objek sementara dari Canvas setelah prefab dibuat.

🏆 LEADERBOARD

Contoh tampilan — data ilustrasi
🥇Budi Santoso
Peringkat 1
950
🥈Siti Rahma
Peringkat 2
880
🥉Andi Wijaya
Peringkat 3
820

7. Membuat Model Data JSON

Buat folder Assets/Scripts, lalu buat file LeaderboardModels.cs. Class ini menyesuaikan struktur JSON dengan objek C#.

using System;

[Serializable]
public class LeaderboardEntry
{
    public int rank;
    public int id;
    public string nama;
    public int nilai;
    public string created_at;
}

[Serializable]
public class LeaderboardResponse
{
    public string status;
    public int total;
    public LeaderboardEntry[] data;
}

[Serializable]
public class LeaderboardSubmit
{
    public string nama;
    public int nilai;
}
  • LeaderboardEntry: satu baris data pemain.
  • LeaderboardResponse: respons GET yang berisi status, total, dan array data.
  • LeaderboardSubmit: data nama dan nilai yang akan dikirim ke server.
  • [Serializable]: memungkinkan JsonUtility melakukan serialisasi/deserialisasi objek.
Model di atas mengasumsikan nilai dikirim sebagai angka JSON, seperti pada contoh API. Jika server mengirimnya sebagai string, sesuaikan tipe datanya.

8. Script untuk Satu Baris UI

Buat file LeaderboardItemUI.cs, lalu pasang pada prefab LeaderboardItem.

using TMPro;
using UnityEngine;

public class LeaderboardItemUI : MonoBehaviour
{
    public TMP_Text rankText;
    public TMP_Text namaText;
    public TMP_Text nilaiText;
    public TMP_Text tanggalText;

    public void SetData(LeaderboardEntry entry)
    {
        rankText.text = "#" + entry.rank;
        namaText.text = entry.nama;
        nilaiText.text = entry.nilai.ToString();
        tanggalText.text = entry.created_at;
    }
}

Di Inspector prefab, hubungkan setiap field ke objek TextMeshPro yang sesuai. Method SetData() akan mengisi teks ketika data pemain diterima.

9. Script Utama: GET, POST (WWWForm & JSON), dan Refresh

Buat file LeaderboardManager.cs. Script ini mengunduh data, membangun baris UI, mendukung 2 cara pengiriman POST (JSON & WWWForm) yang dapat dipilih melalui Inspector, serta memuat ulang data secara otomatis setelah pengiriman berhasil.

using System.Collections;
using System.Text;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;

public class LeaderboardManager : MonoBehaviour
{
    public enum MetodePengiriman
    {
        JSON,
        WWWForm
    }

    private const string API_URL =
        "https://simple-api.appocket.id/simple-leaderboard";

    [Header("Metode Pengiriman POST")]
    [Tooltip("Pilih cara pengiriman data skor ke server: format JSON atau WWWForm")]
    public MetodePengiriman metodeKirim = MetodePengiriman.JSON;

    [Header("Leaderboard UI")]
    public Transform content;
    public GameObject leaderboardItemPrefab;
    public int limit = 10;

    [Header("Input UI")]
    public TMP_InputField namaInput;
    public TMP_InputField nilaiInput;

    [Header("Status UI")]
    public TMP_Text statusText;

    private bool isProcessing;

    private void Start()
    {
        StartCoroutine(GetLeaderboard());
    }

    // GET: mengambil data leaderboard
    public IEnumerator GetLeaderboard()
    {
        string url = API_URL + "?limit=" + Mathf.Max(1, limit);

        using (UnityWebRequest request = UnityWebRequest.Get(url))
        {
            request.timeout = 15;
            yield return request.SendWebRequest();

            if (request.result != UnityWebRequest.Result.Success)
            {
                SetStatus("Gagal mengambil data: " + request.error);
                Debug.LogError("GET Error: " + request.error +
                    "\nResponse: " + request.downloadHandler.text);
                yield break;
            }

            string json = request.downloadHandler.text;
            Debug.Log("GET Response: " + json);

            LeaderboardResponse response;
            try
            {
                response = JsonUtility.FromJson(json);
            }
            catch (System.Exception e)
            {
                SetStatus("Gagal membaca JSON.");
                Debug.LogError(e.Message);
                yield break;
            }

            if (response == null || response.status != "success"
                || response.data == null)
            {
                SetStatus("Format data leaderboard tidak valid.");
                yield break;
            }

            DisplayLeaderboard(response.data);
            SetStatus("Leaderboard berhasil dimuat: " +
                response.total + " data.");
        }
    }

    private void DisplayLeaderboard(LeaderboardEntry[] entries)
    {
        // Hapus baris lama agar tidak terjadi duplikasi.
        foreach (Transform child in content)
        {
            Destroy(child.gameObject);
        }

        foreach (LeaderboardEntry entry in entries)
        {
            GameObject item = Instantiate(leaderboardItemPrefab, content);
            LeaderboardItemUI itemUI = item.GetComponent();

            if (itemUI != null)
            {
                itemUI.SetData(entry);
            }
            else
            {
                Debug.LogError("Prefab tidak memiliki LeaderboardItemUI.");
            }
        }
    }

    // POST: validasi input sebelum mengirim skor
    public void SubmitScore()
    {
        if (isProcessing)
            return;

        string nama = namaInput.text.Trim();
        string nilaiString = nilaiInput.text.Trim();

        if (string.IsNullOrEmpty(nama))
        {
            SetStatus("Nama pemain harus diisi.");
            return;
        }

        if (!int.TryParse(nilaiString, out int nilai) || nilai < 0)
        {
            SetStatus("Nilai harus berupa angka 0 atau lebih.");
            return;
        }

        // Jalankan pengiriman sesuai metode yang dipilih di Inspector
        if (metodeKirim == MetodePengiriman.JSON)
        {
            StartCoroutine(PostLeaderboardJSON(nama, nilai));
        }
        else
        {
            StartCoroutine(PostLeaderboardWWWForm(nama, nilai));
        }
    }

    // =========================================================================
    // CARA 1: Mengirim Data Skor Menggunakan Format JSON (application/json)
    // =========================================================================
    private IEnumerator PostLeaderboardJSON(string nama, int nilai)
    {
        isProcessing = true;
        SetStatus("Mengirim skor via JSON...");

        // 1. Bungkus data ke class model lalu serialisasi menjadi teks JSON
        LeaderboardSubmit submitData = new LeaderboardSubmit
        {
            nama = nama,
            nilai = nilai
        };
        string json = JsonUtility.ToJson(submitData);
        byte[] bodyRaw = Encoding.UTF8.GetBytes(json);

        // 2. Buat UnityWebRequest dengan UploadHandlerRaw dan header JSON
        using (UnityWebRequest request = new UnityWebRequest(API_URL, "POST"))
        {
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = new DownloadHandlerBuffer();
            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("Accept", "application/json");
            request.timeout = 15;

            yield return request.SendWebRequest();

            yield return HandlePostResponse(request, "JSON");
        }

        isProcessing = false;
    }

    // =========================================================================
    // CARA 2: Mengirim Data Skor Menggunakan WWWForm (multipart/form-data)
    // =========================================================================
    private IEnumerator PostLeaderboardWWWForm(string nama, int nilai)
    {
        isProcessing = true;
        SetStatus("Mengirim skor via WWWForm...");

        // 1. Buat objek WWWForm dan masukkan pasangan key-value
        WWWForm form = new WWWForm();
        form.AddField("nama", nama);
        form.AddField("nilai", nilai);

        // 2. Gunakan helper method UnityWebRequest.Post bawaan Unity
        using (UnityWebRequest request = UnityWebRequest.Post(API_URL, form))
        {
            request.SetRequestHeader("Accept", "application/json");
            request.timeout = 15;

            yield return request.SendWebRequest();

            yield return HandlePostResponse(request, "WWWForm");
        }

        isProcessing = false;
    }

    // Fungsi pemroses balasan respon server setelah POST
    private IEnumerator HandlePostResponse(UnityWebRequest request, string metode)
    {
        string responseBody = request.downloadHandler != null ? request.downloadHandler.text : "";
        Debug.Log("POST (" + metode + ") Response: " + responseBody);

        if (request.result != UnityWebRequest.Result.Success)
        {
            SetStatus("Gagal mengirim skor: " + request.error);
            Debug.LogError("POST Error: " + request.error + "\nResponse: " + responseBody);
            yield break;
        }

        SetStatus("Skor berhasil dikirim (" + metode + ").");
        namaInput.text = "";
        nilaiInput.text = "";

        // Ambil data terbaru dari server untuk merefresh baris Scroll View
        yield return GetLeaderboard();
    }

    public void RefreshLeaderboard()
    {
        if (!isProcessing)
            StartCoroutine(GetLeaderboard());
    }

    private void SetStatus(string message)
    {
        if (statusText != null)
            statusText.text = message;

        Debug.Log(message);
    }
}

Bagaimana script bekerja?

  • GET: UnityWebRequest.Get(url) meminta data, lalu JsonUtility.FromJson mengubah respons menjadi objek C#.
  • Instantiate: membuat satu prefab untuk setiap pemain di dalam Content.
  • POST Cara 1 (JSON): JsonUtility.ToJson mengubah objek model ke string JSON, dikonversi ke byte array, lalu dikirim dengan UploadHandlerRaw dan header application/json.
  • POST Cara 2 (WWWForm): WWWForm form = new WWWForm() menampung nilai dengan form.AddField(), lalu dikirim via helper bawaan UnityWebRequest.Post(url, form) secara otomatis.
  • Refresh: setelah POST sukses secara HTTP, coroutine GET dijalankan lagi untuk mengambil daftar terbaru.
Penting: script menganggap respons HTTP sukses berarti server menerima data. Jika API memiliki format respons khusus untuk menolak skor, periksa isi respons itu juga sebelum menampilkan pesan berhasil. Kode ini belum membuktikan bahwa skor telah tersimpan secara permanen.

10. Menghubungkan Komponen di Inspector

  1. Buat GameObject kosong bernama LeaderboardManager.
  2. Pasang script LeaderboardManager.cs pada objek tersebut.
  3. Hubungkan field di Inspector sesuai tabel.
FieldObjek / Nilai yang dihubungkanKeterangan
Metode KirimJSON atau WWWFormPilih cara pengiriman data POST ke server
ContentContent di Scroll ViewTempat prefab baris leaderboard dimunculkan
Leaderboard Item PrefabPrefab LeaderboardItemTemplate baris tampilan data pemain
Limit10Jumlah data skor yang ingin ditampilkan
Nama InputNamaInputTMP_InputField untuk input nama
Nilai InputNilaiInputTMP_InputField untuk input skor
Status TextStatusTextTMP_Text untuk pesan feedback status

Hubungkan tombol Kirim

  1. Pilih KirimButton di Hierarchy.
  2. Di komponen Button, cari bagian On Click(), lalu tekan tombol +.
  3. Seret GameObject LeaderboardManager ke slot objek.
  4. Pilih LeaderboardManager → SubmitScore().

Hubungkan tombol Refresh

Ulangi langkah di atas pada RefreshButton, lalu pilih LeaderboardManager → RefreshLeaderboard().

Atur NilaiInput dengan Content Type Integer Number. Pastikan prefab LeaderboardItem memiliki script LeaderboardItemUI dan semua field teks sudah terhubung.

11. Pengujian Praktik

  1. Jalankan game (Play Mode). Method Start() otomatis meminta data leaderboard (GET).
  2. Pastikan data skor pemain muncul teratur sebagai baris-baris di dalam Scroll View.
  3. Uji Pengiriman Skor (Cara 1 - JSON):
    • Pada objek LeaderboardManager di Inspector, pastikan Metode Kirim diset ke JSON.
    • Ketikkan nama Rian Ardiansyah dan nilai 920.
    • Tekan tombol Kirim. Periksa status dan tab Console. Pastikan log menampilkan [JSON SUKSES] dan data baru langsung muncul di Scroll View.
  4. Uji Pengiriman Skor (Cara 2 - WWWForm):
    • Ganti opsi Metode Kirim di Inspector menjadi WWWForm.
    • Ketikkan nama Siti Aminah dan nilai 960.
    • Tekan tombol Kirim lagi. Pastikan pengiriman via form-data juga sukses dan data peringkat terupdate ke posisi teratas.
  5. Tekan tombol Refresh kapan pun untuk memvalidasi pengambilan ulang data terbaru secara manual.

Checklist hasil praktik

12. Troubleshooting & Optimasi

MasalahYang perlu diperiksa
Data tidak munculPeriksa URL, koneksi internet, respons server, dan Console Unity.
Gagal membaca JSONPastikan respons memiliki status, total, dan data sesuai contoh.
Baris bertumpukPeriksa Vertical Layout Group, Content Size Fitter, dan tinggi prefab.
Tombol tidak bekerjaPeriksa event On Click dan referensi GameObject.
POST gagalPeriksa HTTP status, header Content-Type, nama field JSON, dan respons server.
Peringkat tidak berubahPastikan server menyimpan data dan endpoint GET mengembalikan data terbaru.
Kesimpulan: dengan UnityWebRequest, model data C#, prefab UI, dan Scroll View, leaderboard dapat mengambil dan mengirim data secara dinamis tanpa membuat baris pemain satu per satu.

Catatan keamanan: endpoint pada modul ini menggunakan HTTPS dan tidak memerlukan token menurut spesifikasi yang diberikan. Untuk game produksi, validasi skor di server agar client tidak bisa mengirim skor palsu.

Bagian 1 dari 10 Belum Selesai
Notifikasi