Bekerja dengan banyak adegan di Unity bisa jadi menantang, dan mengoptimalkan alur kerja ini berdampak besar pada performa game dan produktivitas tim Anda. Hari ini kami akan berbagi dengan Anda tip untuk menyiapkan alur kerja dengan Scene yang dapat diskalakan ke proyek yang lebih besar.
Sebagian besar game memiliki beberapa level, dan level sering kali berisi lebih dari satu adegan. Dalam game yang adegannya relatif kecil, Anda dapat memecahnya menjadi beberapa bagian menggunakan Prefab. Namun, untuk menghubungkan atau membuat instance selama permainan, Anda perlu mereferensikan semua prefab ini. Ini berarti bahwa saat game Anda semakin besar dan tautan ini menggunakan lebih banyak ruang memori, penggunaan adegan menjadi lebih efisien.
Anda dapat membagi level menjadi satu atau lebih Unity Scenes. Menemukan cara terbaik untuk mengelolanya menjadi poin kunci. Anda dapat membuka beberapa adegan sekaligus di editor dan saat runtime menggunakan fitur pengeditan Multi-Pemandangan . Memisahkan lapisan menjadi beberapa adegan juga membuat kerja tim lebih mudah, karena menghindari konflik gabungan di alat kolaborasi seperti Git, SVN, Unity Collaborate, dan banyak lagi.
Kelola banyak adegan untuk membuat level
Dalam video di bawah ini, kami akan menunjukkan kepada Anda cara memuat level secara lebih efisien dengan memecah logika game dan berbagai bagian level menjadi beberapa adegan Unity terpisah. Kemudian, menggunakan mode Pemuatan Aditif Aditif saat memuat adegan itu, kami memuat dan membongkar bagian yang diperlukan bersama dengan logika permainan yang tidak ke mana-mana. Kami menggunakan prefab sebagai jangkar untuk adegan, yang juga memberikan lebih banyak fleksibilitas saat bekerja sebagai tim, karena setiap adegan adalah bagian dari level dan dapat diedit secara terpisah.
Anda masih dapat memuat pemandangan ini dalam mode edit dan menekan Mainkan kapan saja untuk membuat semuanya bersamaan saat Anda mengerjakan desain level.
Kami akan menunjukkan dua metode berbeda untuk memuat adegan ini. Yang pertama didasarkan pada jarak, yang bekerja dengan baik untuk tingkat non-interior seperti dunia terbuka. Teknik ini juga berguna untuk beberapa efek visual (seperti kabut) untuk menyembunyikan proses bongkar muat.
Metode kedua menggunakan Trigger untuk memeriksa adegan mana yang perlu dimuat, yang lebih efisien saat bekerja dengan interior.
Sekarang kita telah mengetahui semua yang ada di dalam level, kita dapat menambahkan lapisan tambahan di atasnya untuk mengelola level itu sendiri dengan lebih baik.
Mengontrol beberapa level game dengan ScriptableObjects
Kami ingin melacak berbagai adegan di setiap level, serta semua level di seluruh gameplay. Salah satu cara yang mungkin untuk mencapai ini adalah dengan menggunakan variabel statis dan singletones dalam skrip MonoBehaviour, tetapi solusi ini tidak begitu mulus. Menggunakan singleton menyiratkan hubungan erat antara sistem Anda, jadi ini tidak sepenuhnya modular. Sistem tidak bisa ada secara terpisah dan akan selalu bergantung satu sama lain.
Masalah lain terkait dengan penggunaan variabel statis. Karena Anda tidak dapat melihatnya di Inspektur, Anda perlu menentukannya melalui kode, yang mempersulit artis atau perancang level untuk menguji permainan. Saat Anda membutuhkan data untuk dibagikan di antara adegan yang berbeda, Anda menggunakan variabel statis bersama dengan DontDestroyOnLoad, tetapi variabel statis harus dihindari jika memungkinkan.
Untuk menyimpan informasi tentang berbagai pemandangan, Anda dapat menggunakan ScriptableObject , kelas yang dapat bersambung yang terutama digunakan untuk menyimpan data. Tidak seperti skrip MonoBehaviour, yang digunakan sebagai komponen yang terikat ke GameObjects, ScriptableObjects tidak terikat ke GameObject mana pun dan dengan demikian dapat digunakan oleh pemandangan yang berbeda di seluruh proyek.
Alangkah baiknya dapat menggunakan struktur ini untuk level serta adegan menu di game Anda. Untuk melakukan ini, buat kelas GameScene yang berisi berbagai properti umum untuk level dan menu.
public class GameScene : ScriptableObject
{
[Header("Information")]
public string sceneName;
public string shortDescription;
[Header("Sounds")]
public AudioClip music;
[Range(0.0f, 1.0f)]
public float musicVolume;
[Header("Visuals")]
public PostProcessProfile postprocess;
}
Perhatikan bahwa kelas mewarisi dari ScriptableObject, bukan MonoBehaviour. Anda dapat menambahkan properti sebanyak yang diperlukan untuk game Anda. Setelah langkah ini, Anda dapat membuat kelas Level dan Menu yang mewarisi dari kelas GameScene yang baru saja Anda buat, jadi mereka juga merupakan ScriptableObjects.
[CreateAssetMenu(fileName = "NewLevel", menuName = "Scene Data/Level")]
public class Level : GameScene
{
// ,
[Header("Level specific")]
public int enemiesCount;
}
Menambahkan atribut CreateAssetMenu di bagian atas memungkinkan Anda membuat level baru dari menu Assets di Unity. Anda dapat melakukan hal yang sama untuk kelas Menu. Anda juga dapat menambahkan enumerasi untuk dapat memilih jenis menu dari inspektur.
public enum Type
{
Main_Menu,
Pause_Menu
}
[CreateAssetMenu(fileName = "NewMenu", menuName = "Scene Data/Menu")]
public class Menu : GameScene
{
// ,
[Header("Menu specific")]
public Type type;
}
Sekarang Anda dapat membuat level dan menu, mari tambahkan database yang mencantumkannya (level dan menu) untuk kenyamanan. Anda juga dapat menambahkan indeks untuk melacak level pemain saat ini. Anda kemudian dapat menambahkan metode untuk memuat game baru (dalam hal ini level pertama akan dimuat), untuk mengulangi level saat ini, dan untuk melanjutkan ke level berikutnya. Perhatikan bahwa hanya indeks yang diubah dalam ketiga metode ini, sehingga Anda dapat membuat metode yang memuat level demi indeks untuk menggunakannya kembali.
[CreateAssetMenu(fileName = "sceneDB", menuName = "Scene Data/Database")]
public class ScenesData : ScriptableObject
{
public List<Level> levels = new List<Level>();
public List<Menu> menus = new List<Menu>();
public int CurrentLevelIndex=1;
/*
*
*/
//
public void LoadLevelWithIndex(int index)
{
if (index <= levels.Count)
{
//
SceneManager.LoadSceneAsync("Gameplay" + index.ToString());
//
SceneManager.LoadSceneAsync("Level" + index.ToString() + "Part1", LoadSceneMode.Additive);
}
// ,
else CurrentLevelIndex =1;
}
//
public void NextLevel()
{
CurrentLevelIndex++;
LoadLevelWithIndex(CurrentLevelIndex);
}
//
public void RestartLevel()
{
LoadLevelWithIndex(CurrentLevelIndex);
}
// ,
public void NewGame()
{
LoadLevelWithIndex(1);
}
/*
*
*/
//
public void LoadMainMenu()
{
SceneManager.LoadSceneAsync(menus[(int)Type.Main_Menu].sceneName);
}
//
public void LoadPauseMenu()
{
SceneManager.LoadSceneAsync(menus[(int)Type.Pause_Menu].sceneName);
}
Ada juga metode menu, dan Anda dapat menggunakan jenis pencacahan yang Anda buat sebelumnya untuk memuat menu tertentu yang Anda butuhkan - pastikan saja urutan pencacahan dan urutan dalam daftar menu sama.
Terakhir, Anda sekarang dapat membuat level database, menu atau ScriptableObject dari menu Assets dengan mengklik kanan di jendela Project.
Dari sana, terus tambahkan level dan menu yang Anda inginkan, sesuaikan parameter dan kemudian tambahkan ke database adegan. Contoh di bawah ini menunjukkan seperti apa data Level1, MainMenu, dan Pemandangan.
Saatnya memanggil metode ini. Dalam contoh ini, tombol Level Berikutnya di antarmuka pengguna (UI) yang muncul saat pemain mencapai akhir level memanggil metode NextLevel. Untuk mengikat metode ke tombol, klik tombol dengan acara On Click plus komponen Tombol untuk menambahkan acara baru, lalu seret Scene Data ScriptableObject ke bidang objek dan pilih metode NextLevel dari ScenesData seperti yang ditunjukkan di bawah ini.
Sekarang Anda dapat melakukan proses yang sama untuk tombol lain - memutar ulang level atau membuka menu utama dan seterusnya. Anda juga dapat merujuk ke ScriptableObject dari skrip lain untuk mengakses berbagai properti seperti AudioClip untuk musik latar atau profil pasca-pemrosesan dan menggunakannya di tingkat.
Tip untuk Meminimalkan Kesalahan dalam Proses Anda
Meminimalkan Pemuatan /
Pembongkaran Dalam skrip ScenePartLoader yang ditampilkan di video, Anda dapat melihat bahwa pemutar dapat terus masuk dan keluar dari collider beberapa kali, menyebabkan adegan dimuat ulang dan dibongkar. Untuk menghindari hal ini, Anda dapat menambahkan coroutine sebelum memanggil metode pemuatan dan pembongkaran adegan dalam skrip dan menghentikan coroutine jika pemain meninggalkan pemicu.
Konvensi penamaan
Tip global lainnya adalah menggunakan konvensi penamaan yang kuat dalam proyek Anda. Tim harus menyetujui sebelumnya tentang bagaimana memberi nama berbagai jenis aset, dari skrip dan adegan hingga materi dan hal-hal lain dalam proyek. Ini akan membuatnya lebih mudah untuk mengerjakan proyek dan mendukungnya tidak hanya untuk Anda, tetapi juga untuk rekan satu tim Anda. Itu selalu merupakan ide yang bagus, tetapi dalam kasus khusus ini sangat penting untuk mengelola adegan dengan ScriptableObjects. Contoh kami menggunakan pendekatan berbasis nama adegan sederhana, tetapi ada banyak solusi berbeda yang kurang mengandalkan nama adegan. Anda harus menghindari pendekatan berbasis string karena jika Anda mengganti nama scene Unity dalam konteks ini, scene tersebut tidak akan dimuat di tempat lain dalam game.
Alat khusus
Salah satu cara untuk menghindari ketergantungan pada nama di sepanjang permainan adalah dengan mengkonfigurasi skrip Anda untuk merujuk ke adegan sebagai tipe Object . Ini memungkinkan Anda untuk menyeret dan melepaskan sumber daya adegan di inspektur dan kemudian diam-diam mendapatkan namanya di skrip. Namun, karena ini adalah kelas Editor, Anda tidak memiliki akses ke kelas AssetDatabase pada waktu proses, jadi Anda perlu menggabungkan kedua bagian data untuk solusi yang berfungsi di editor, mencegah kesalahan manusia, dan masih berfungsi pada waktu proses. Anda dapat merujuk ke antarmuka ISerializationCallbackReceiver untuk contoh cara mengimplementasikan objek yang, setelah serialisasi, dapat mengambil jalur string dari aset Scene dan menyimpannya untuk penggunaan runtime.
Sebagai alternatif, Anda juga dapat membuat inspektur Anda sendiri untuk mempermudah menambahkan adegan dengan cepat ke Pengaturan Build menggunakan tombol, daripada menambahkannya secara manual melalui menu ini dan menjaganya tetap sinkron.
Untuk contoh alat jenis ini, lihat implementasi sumber terbuka yang luar biasa ini dari pengembang JohannesMP (ini bukan sumber daya Unity resmi).
Beri tahu kami pendapat Anda
Posting ini hanya menunjukkan satu cara ScriptableObjects dapat meningkatkan alur kerja Anda saat bekerja dengan banyak adegan yang dikombinasikan dengan prefab. Game yang berbeda menggunakan cara yang sama sekali berbeda untuk mengontrol adegan - tidak ada solusi tunggal yang cocok untuk semua struktur game sekaligus. Masuk akal untuk menerapkan alat Anda sendiri yang sesuai dengan organisasi proyek Anda.
Kami berharap informasi ini akan membantu proyek Anda, atau mungkin menginspirasi Anda untuk membuat alat manajemen adegan sendiri.
Beri tahu kami di komentar jika Anda memiliki pertanyaan. Kami ingin mendengar teknik apa yang Anda gunakan untuk memanipulasi adegan dalam game Anda. Dan jangan ragu untuk menyarankan kasus penggunaan lain yang ingin Anda sarankan untuk dipertimbangkan di posting selanjutnya.