Temukan potensi WebGL dengan pemandangan yang dihasilkan secara prosedural dan tanpa batas dari game mengemudi kasual ini.
Slow Roads adalah game mengemudi kasual dengan penekanan pada pemandangan yang dihasilkan secara prosedural tanpa henti, semuanya dihosting di browser sebagai aplikasi WebGL. Bagi banyak orang, pengalaman intens seperti itu mungkin tampak tidak sesuai dalam konteks browser yang terbatas—dan memang, memperbaiki sikap tersebut adalah salah satu tujuan saya dengan project ini. Dalam artikel ini, saya akan menguraikan beberapa teknik yang saya gunakan untuk mengatasi hambatan performa dalam misi saya untuk menyoroti potensi 3D yang sering diabaikan di web.
Pengembangan 3D di browser
Setelah merilis Jalan Lambat, saya melihat komentar berulang dalam masukan: "Saya tidak tahu ini bisa dilakukan di browser". Jika Anda memiliki sentimen yang sama, Anda tentu bukan minoritas; menurut survei Kondisi JS 2022, sekitar 80% developer belum bereksperimen dengan WebGL. Bagi saya, sangat disayangkan jika begitu banyak potensi yang mungkin terlewatkan, terutama dalam hal game berbasis browser. Dengan Slow Roads, saya berharap dapat lebih mempopulerkan WebGL, dan mungkin mengurangi jumlah developer yang ragu dengan frasa "engine game JavaScript performa tinggi".
WebGL mungkin tampak misterius dan rumit bagi banyak orang, tetapi dalam beberapa tahun terakhir, ekosistem pengembangannya telah berkembang pesat menjadi alat dan library yang sangat mampu dan praktis. Kini, developer frontend dapat dengan mudah menggabungkan UX 3D ke dalam pekerjaan mereka, bahkan tanpa pengalaman sebelumnya dalam grafik komputer. Three.js, library WebGL terkemuka, berfungsi sebagai fondasi untuk banyak perluasan, termasuk react-three-fiber yang menghadirkan komponen 3D ke dalam framework React. Kini ada juga editor game berbasis web yang komprehensif seperti Babylon.js atau PlayCanvas yang menawarkan antarmuka yang sudah dikenal dan toolchain terintegrasi.
Namun, meskipun utilitas library ini luar biasa, project ambisius pada akhirnya dibatasi oleh batasan teknis. Orang yang meragukan ide game berbasis browser mungkin menyoroti bahwa JavaScript adalah single-thread dan memiliki keterbatasan resource. Namun, mengatasi batasan ini akan membuka nilai tersembunyi: tidak ada platform lain yang menawarkan aksesibilitas instan dan kompatibilitas massal yang sama yang diaktifkan oleh browser. Pengguna di sistem yang kompatibel dengan browser dapat mulai memutar dengan sekali klik, tanpa perlu menginstal aplikasi dan tanpa perlu login ke layanan. Belum lagi developer menikmati kemudahan yang elegan dengan memiliki framework frontend yang andal yang tersedia untuk mem-build UI, atau menangani jaringan untuk mode multiplayer. Menurut saya, nilai-nilai ini adalah yang membuat browser menjadi platform yang sangat baik bagi pemain dan developer—dan, seperti yang ditunjukkan oleh Slow Roads, batasan teknis mungkin sering kali dapat dikurangi menjadi masalah desain.
Mendapatkan performa yang lancar di Jalan Lambat
Karena elemen inti Slow Roads melibatkan gerakan berkecepatan tinggi dan pembuatan pemandangan yang mahal, kebutuhan akan performa yang lancar menandai setiap keputusan desain saya. Strategi utama saya adalah memulai dengan desain gameplay yang disederhanakan yang memungkinkan pintasan kontekstual dilakukan dalam arsitektur mesin. Di sisi lain, hal ini berarti mengorbankan beberapa fitur yang bagus untuk dimiliki dalam upaya mencapai minimalisme, tetapi menghasilkan sistem yang dioptimalkan secara khusus dan hiper yang berfungsi dengan baik di berbagai browser dan perangkat.
Berikut adalah perincian komponen utama yang membuat Slow Roads tetap ramping.
Membentuk mesin lingkungan di sekitar gameplay
Sebagai komponen utama game, mesin pembuatan lingkungan tidak dapat dihindari harganya mahal, yang secara wajar mengambil proporsi terbesar dari anggaran untuk memori dan komputasi. Trik yang digunakan di sini adalah dalam menjadwalkan dan mendistribusikan komputasi berat selama suatu jangka waktu, agar tidak mengganggu kecepatan frame dengan lonjakan performa.
Lingkungan terdiri dari ubin geometri, yang berbeda ukuran dan resolusinya (dikategorikan sebagai "tingkat detail" atau LoD) bergantung pada seberapa dekat ubin akan muncul ke kamera. Dalam game biasa dengan kamera bebas roaming, LoD yang berbeda harus terus dimuat dan dimuat ulang untuk mendetailkan lingkungan pemain di mana pun mereka memilih untuk pergi. Hal ini dapat menjadi operasi yang mahal dan boros, terutama jika lingkungan itu sendiri dibuat secara dinamis. Untungnya, konvensi ini dapat sepenuhnya diubah di Jalan Lambat karena ekspektasi kontekstual bahwa pengguna harus tetap berada di jalan. Sebagai gantinya, geometri dengan detail tinggi dapat dicadangkan untuk koridor sempit yang langsung mengapit rute.

Garis tengah jalan itu sendiri dibuat jauh sebelum pemain tiba, sehingga memungkinkan prediksi yang akurat tentang waktu dan tempat detail lingkungan akan diperlukan. Hasilnya adalah sistem ramping yang dapat menjadwalkan pekerjaan mahal secara proaktif, hanya menghasilkan minimum yang diperlukan pada setiap titik waktu, dan tanpa membuang tenaga pada detail yang tidak akan terlihat. Teknik ini hanya dapat dilakukan karena jalan adalah satu jalur yang tidak bercabang—contoh yang baik untuk membuat kompromi gameplay yang mengakomodasi jalan pintas arsitektur.

Memilih-milih hukum fisika
Simulasi fisika adalah yang kedua setelah permintaan komputasi mesin lingkungan. Slow Roads menggunakan mesin fisika kustom minimal yang menggunakan setiap pintasan yang tersedia.
Penghematan utama di sini adalah untuk menghindari simulasi terlalu banyak objek sejak awal—dengan beralih ke konteks zen yang minimal dengan mendiskon hal-hal seperti tabrakan dinamis dan objek yang dapat dihancurkan. Asumsi bahwa kendaraan akan tetap berada di jalan berarti bahwa tabrakan dengan objek di luar jalan dapat diabaikan secara wajar. Selain itu, encoding jalan sebagai median yang jarang memungkinkan trik yang elegan untuk mendeteksi tabrakan dengan permukaan jalan dan pagar pengaman dengan cepat, semuanya didasarkan pada pemeriksaan jarak ke pusat jalan. Mengemudi di luar jalan kemudian menjadi lebih mahal, tetapi ini adalah contoh lain dari kompromi yang adil yang sesuai dengan konteks gameplay.
Mengelola jejak memori
Sebagai resource lain yang dibatasi browser, penting untuk mengelola memori dengan hati-hati—meskipun JavaScript dibersihkan sampah memorinya. Hal ini mudah diabaikan, tetapi mendeklarasikan memori baru dalam jumlah kecil dalam loop game dapat menyebabkan masalah yang signifikan saat berjalan pada 60 Hz. Selain menghabiskan resource pengguna dalam konteks saat mereka kemungkinan melakukan multitasking, pembersihan sampah memori yang besar dapat memerlukan beberapa frame untuk diselesaikan, sehingga menyebabkan gangguan yang terlihat. Untuk menghindari hal ini, memori loop dapat dialokasikan sebelumnya dalam variabel class saat inisialisasi dan didaur ulang di setiap frame.

Struktur data yang lebih berat, seperti geometri dan buffer data terkait, juga harus dikelola secara ekonomis. Dalam game yang dibuat tanpa batas seperti Slow Roads, sebagian besar geometri ada di semacam treadmill - setelah bagian lama tertinggal di kejauhan, struktur datanya dapat disimpan dan didaur ulang lagi untuk bagian dunia yang akan datang, sebuah pola desain yang dikenal sebagai penggabungan objek.
Praktik ini membantu memprioritaskan eksekusi yang ramping, dengan mengorbankan beberapa kesederhanaan kode. Dalam konteks performa tinggi, penting untuk memperhatikan bagaimana fitur praktis terkadang meminjam dari klien untuk kepentingan developer. Misalnya, metode
seperti Object.keys()
atau Array.map()
sangat praktis, tetapi mudah untuk mengabaikan bahwa setiap metode membuat array baru untuk nilai
yang ditampilkan. Memahami cara kerja bagian dalam black box tersebut dapat membantu memperketat kode Anda dan menghindari penurunan performa yang tersembunyi.
Mengurangi waktu pemuatan dengan aset yang dibuat secara prosedural
Meskipun performa runtime harus menjadi perhatian utama bagi developer game, aksioma umum terkait waktu pemuatan halaman web awal masih berlaku. Pengguna mungkin lebih memaklumi jika mereka mengetahui bahwa mereka mengakses konten yang berat, tetapi waktu pemuatan yang lama tetap dapat merusak pengalaman, jika bukan retensi pengguna. Game sering kali memerlukan aset besar dalam bentuk tekstur, suara, dan model 3D, dan setidaknya aset ini harus dikompresi dengan cermat di mana detail dapat dihemat.
Atau, membuat aset secara terstruktur di klien dapat menghindari transfer yang lama. Hal ini merupakan manfaat besar bagi pengguna dengan koneksi lambat, dan memberi developer kontrol yang lebih langsung atas cara game mereka disusun—tidak hanya untuk langkah pemuatan awal, tetapi juga dalam hal menyesuaikan tingkat detail untuk berbagai setelan kualitas.
Sebagian besar geometri di Jalan Lambat dibuat secara terstruktur dan sederhana, dengan shader kustom yang menggabungkan beberapa tekstur untuk menghadirkan detail. Kelemahannya adalah tekstur ini dapat menjadi aset yang berat, meskipun ada peluang penghematan lebih lanjut di sini, dengan metode seperti tekstur stohastik yang dapat mencapai detail yang lebih besar dari tekstur sumber kecil. Dan pada tingkat ekstrem, Anda juga dapat membuat tekstur sepenuhnya di klien dengan alat seperti texgen.js. Hal yang sama juga berlaku untuk audio, dengan Web Audio API yang memungkinkan pembuatan suara dengan node audio.
Dengan manfaat aset prosedural, pembuatan lingkungan awal hanya memerlukan waktu rata-rata 3,2 detik. Untuk memanfaatkan ukuran download awal yang kecil dengan sebaik mungkin, layar pembuka sederhana akan menyambut pengunjung baru dan menunda inisialisasi scene yang mahal hingga setelah tombol afirmatif ditekan. Hal ini juga berfungsi sebagai buffer yang mudah untuk sesi yang dikembalikan, sehingga meminimalkan pemborosan transfer aset yang dimuat secara dinamis.
Mengambil pendekatan yang lincah untuk pengoptimalan terlambat
Saya selalu menganggap codebase untuk Slow Roads bersifat eksperimental, dan dengan demikian telah mengambil pendekatan yang sangat lincah untuk pengembangan. Saat menangani arsitektur sistem yang kompleks dan berkembang pesat, sulit untuk memprediksi tempat terjadinya bottleneck penting. Fokusnya harus pada penerapan fitur yang diinginkan dengan cepat, bukan dengan rapi, lalu melakukan pekerjaan mundur untuk mengoptimalkan sistem yang benar-benar penting. Profiler performa di Chrome DevTools sangat penting untuk langkah ini, dan telah membantu saya mendiagnosis beberapa masalah utama pada versi game sebelumnya. Waktu Anda sebagai developer sangat berharga, jadi pastikan Anda tidak menghabiskan waktu untuk mempertimbangkan masalah yang mungkin terbukti tidak signifikan atau berlebihan.
Memantau pengalaman pengguna
Saat menerapkan semua trik ini, penting untuk memastikan game berperforma seperti yang diharapkan di dunia nyata. Menyesuaikan berbagai kemampuan hardware adalah aspek utama dari pengembangan game apa pun, tetapi game web dapat menargetkan spektrum yang jauh lebih luas yang terdiri dari desktop kelas atas dan perangkat seluler yang sudah berumur satu dekade sekaligus. Cara termudah untuk mengatasi hal ini adalah dengan menawarkan setelan untuk menyesuaikan bottleneck yang paling mungkin terjadi di codebase Anda—untuk tugas yang intensif GPU dan CPU—seperti yang diungkapkan oleh profiler Anda.
Namun, pembuatan profil di komputer Anda sendiri hanya dapat mencakup banyak hal, jadi sebaiknya tutup lingkaran umpan balik dengan pengguna Anda dengan cara tertentu. Untuk Jalan Lambat, saya menjalankan analisis sederhana yang melaporkan performa beserta faktor kontekstual seperti resolusi layar. Analisis ini dikirim ke backend Node dasar menggunakan socket.io, beserta masukan tertulis apa pun yang dikirimkan pengguna melalui formulir dalam game. Pada awalnya, analisis ini menangkap banyak masalah penting yang dapat dimitigasi dengan perubahan sederhana pada UX, seperti menandai menu setelan saat FPS yang rendah secara konsisten terdeteksi, atau memperingatkan bahwa pengguna mungkin perlu mengaktifkan akselerasi hardware jika performanya sangat buruk.
Jalan lambat di depan
Meskipun setelah melakukan semua tindakan ini, masih ada sebagian besar basis pemain yang perlu bermain pada setelan yang lebih rendah—terutama yang menggunakan perangkat ringan yang tidak memiliki GPU. Meskipun rentang setelan kualitas yang tersedia menghasilkan distribusi performa yang cukup merata, hanya 52% pemain yang mencapai di atas 55 FPS.

Untungnya, masih ada banyak peluang untuk menghemat performa. Selain menambahkan trik rendering lebih lanjut untuk mengurangi permintaan GPU, saya berharap dapat bereksperimen dengan pekerja web dalam melakukan paralelisasi pembuatan lingkungan dalam waktu dekat, dan pada akhirnya mungkin melihat perlunya menggabungkan WASM atau WebGPU ke dalam codebase. Setiap headroom yang dapat saya kosongkan akan memungkinkan lingkungan yang lebih kaya dan lebih beragam, yang akan menjadi sasaran berkelanjutan untuk sisa project.
Seperti proyek hobi lainnya, Slow Roads telah menjadi cara yang sangat memuaskan untuk menunjukkan betapa rumit, berperforma tinggi, dan populernya game browser. Jika saya berhasil membangkitkan minat Anda pada WebGL, ketahuilah bahwa Jalan Lambat teknologi adalah contoh yang cukup dangkal dari kemampuan lengkapnya. Saya sangat menyarankan pembaca untuk menjelajahi presentasi Three.js, dan bagi yang tertarik dengan pengembangan game web secara khusus, Anda dapat bergabung dengan komunitas di webgamedev.com.