Saya telah melihat beberapa video dan tutorial untuk membuat objek singleton di Unity, terutama untuk a GameManager
, yang tampaknya menggunakan pendekatan berbeda untuk membuat instance dan memvalidasi singleton.
Apakah ada pendekatan yang benar, atau lebih tepatnya, lebih disukai untuk ini?
Dua contoh utama yang saya temui adalah:
Pertama
public class GameManager
{
private static GameManager _instance;
public static GameManager Instance
{
get
{
if(_instance == null)
{
_instance = GameObject.FindObjectOfType<GameManager>();
}
return _instance;
}
}
void Awake()
{
DontDestroyOnLoad(gameObject);
}
}
Kedua
public class GameManager
{
private static GameManager _instance;
public static GameManager Instance
{
get
{
if(_instance == null)
{
instance = new GameObject("Game Manager");
instance.AddComponent<GameManager>();
}
return _instance;
}
}
void Awake()
{
_instance = this;
}
}
Perbedaan utama yang bisa saya lihat antara keduanya adalah:
Pendekatan pertama akan mencoba untuk menavigasi tumpukan objek game untuk menemukan contoh GameManager
yang walaupun ini hanya terjadi (atau seharusnya hanya terjadi) sekali tampaknya bisa sangat tidak dioptimalkan sebagai adegan tumbuh dalam ukuran selama pengembangan.
Juga, pendekatan pertama menandai objek yang tidak akan dihapus ketika aplikasi mengubah adegan, yang memastikan bahwa objek tetap ada di antara adegan. Pendekatan kedua tampaknya tidak mematuhi ini.
Pendekatan kedua tampak aneh karena dalam kasus di mana instance adalah null dalam pengambil, itu akan membuat GameObject baru dan menetapkan komponen GameManger untuk itu. Namun, ini tidak dapat berjalan tanpa terlebih dahulu komponen GameManager ini telah dilampirkan ke sebuah objek dalam adegan, jadi ini menyebabkan saya kebingungan.
Apakah ada pendekatan lain yang akan direkomendasikan, atau gabungan dari keduanya di atas? Ada banyak video dan tutorial mengenai lajang, tetapi semuanya sangat berbeda sehingga sulit untuk menarik perbandingan antara keduanya dan dengan demikian, kesimpulan yang mana yang merupakan pendekatan terbaik / disukai.
sumber
GameManager
harus dilakukan, melainkan bagaimana memastikan hanya ada satu contoh objek dan cara terbaik untuk menegakkannya.Jawaban:
Tergantung, tetapi biasanya saya menggunakan metode ketiga. Masalah dengan metode yang Anda gunakan adalah bahwa jika objek dimasukkan untuk memulai, itu tidak akan menghapusnya dari pohon, dan mereka masih dapat dibuat dengan membuat terlalu banyak panggilan, yang dapat membuat hal-hal benar-benar membingungkan.
Masalah dengan kedua implementasi Anda adalah bahwa mereka tidak menghancurkan objek yang dibuat nanti. Itu bisa bekerja, tetapi orang bisa melemparkan kunci inggris ke dalam karya yang bisa mengakibatkan kesalahan debug yang sangat sulit di telepon. Pastikan untuk memeriksa Sedarlah jika sudah ada instance, dan jika demikian, hancurkan instance baru.
sumber
OnDestroy() { if (this == _instance) { _instance = null; } }
, jika Anda ingin memiliki contoh yang berbeda di setiap adegan.Instance
properti statis akan terhapus. Contoh yang tidak dapat ditemukan di salah satu jawaban di bawah ini , atau wiki.unity3d.com/index.php/Singleton (yang mungkin kedaluwarsa, tetapi tampaknya bekerja dari percobaan saya dengan itu)Berikut ringkasan singkatnya:
Jadi, jika yang Anda pedulikan adalah akses global, ketiganya mendapatkan apa yang Anda butuhkan. Penggunaan pola Singleton bisa sedikit ambigu tentang apakah kita ingin instantiasi malas, keunikan yang ditegakkan, atau akses global jadi pastikan untuk berpikir dengan hati-hati tentang mengapa Anda meraih singleton, dan memilih implementasi yang membuat fitur-fitur itu benar, alih-alih daripada menggunakan standar untuk ketiganya saat Anda hanya membutuhkannya.
(mis. jika game saya akan selalu memiliki GameManager, mungkin saya tidak peduli tentang instantiation yang malas - mungkin itu hanya akses global dengan jaminan keberadaan & keunikan yang saya pedulikan - dalam hal ini kelas statis membuat saya persis fitur-fitur itu dengan sangat ringkas, tanpa pertimbangan pemuatan adegan)
... tapi jelas tidak menggunakan Metode 1 seperti yang tertulis. Find dapat dilewati dengan lebih mudah dengan pendekatan Awake () Method2 / 3, dan jika kita menjaga manajer melintasi adegan maka kita sangat mungkin ingin membunuh duplikat, jika kita pernah memuat antara dua adegan dengan manajer yang sudah ada di dalamnya.
sumber
Implementasi terbaik dari
Singleton
pola umum untuk Unity yang saya tahu adalah (tentu saja) milik saya.Ia dapat melakukan segalanya , dan melakukannya dengan rapi dan efisien :
Keuntungan lain:
OnApplicationQuit()
. (Dan ia melakukannya dengan satu bendera global, bukan masing-masing jenis tunggal yang memiliki bendera sendiri)Dan karena berbagi itu peduli , ini dia:
sumber
MonoBehaviour
, dan saya percaya setiap kelas yang digunakan oleh Unity secara langsung.SampleSingletonClass : Singleton
,SampleSingletonClass.Instance
kembali denganSampleSingletonClass does not contain a definition for Instance
.Singleton<>
kelas generik . Itu sebabnya generik adalah anak dariSingleton
kelas dasar .Saya hanya ingin menambahkan bahwa mungkin berguna untuk menelepon
DontDestroyOnLoad
jika Anda ingin singleton Anda bertahan di seluruh adegan.sumber
Pilihan lain mungkin untuk membagi kelas menjadi dua bagian: kelas statis reguler untuk komponen Singleton, dan MonoBehaviour yang bertindak sebagai pengontrol untuk instance singleton. Dengan cara ini Anda memiliki kontrol penuh atas konstruksi singleton, dan itu akan bertahan di seluruh adegan. Ini juga memungkinkan Anda menambahkan pengontrol ke objek apa pun yang mungkin memerlukan data tunggal, alih-alih harus menggali melalui adegan untuk menemukan komponen tertentu.
sumber
Berikut ini adalah implementasi saya dari kelas abstrak tunggal di bawah ini. Berikut adalah bagaimana hal itu sesuai dengan 4 kriteria
Ini memiliki beberapa keunggulan lain dibandingkan dengan beberapa metode lain di sini:
FindObjectsOfType
yang merupakan pembunuh kinerjaIni aman dari utas
sumber
OnApplicationQuitCallback
danOnEnableCallback
sebagaiabstract
bukan hanya kosongvirtual
metode? Setidaknya dalam kasus saya, saya tidak memiliki logika keluar / aktifkan dan memiliki pengesampingan kosong terasa kotor. Tapi saya mungkin kehilangan sesuatu.OnApplicationQuitCallback
danOnEnableCallback
: menjadikannya sebagai metode virtual semacam membuatnya kurang jelas. Mungkin pemikiran yang sedikit aneh tapi sejauh yang saya ingat itu rasional saya.Sebenarnya ada cara resmi palsu untuk menggunakan Singleton di Unity. Inilah penjelasannya, pada dasarnya buat kelas Singleton dan buat skrip Anda mewarisi dari kelas itu.
sumber
Saya akan menganggap implementasi saya juga untuk generasi mendatang.
Bagi saya, baris
Destroy(gameObject.GetComponent(instance.GetType()));
ini sangat penting karena sekali saya meninggalkan skrip singleton pada gim lain. Menangkan adegan dan seluruh objek gim dihapus. Ini hanya akan Hancurkan komponen jika sudah ada.sumber
Saya menulis kelas singleton yang memudahkan untuk membuat objek singleton. Ini adalah skrip MonoBehaviour, sehingga Anda dapat menggunakan Coroutine. Ini berdasarkan pada artikel Wiki Persatuan ini , dan saya akan menambahkan opsi untuk membuatnya dari Prefab nanti.
Jadi, Anda tidak perlu menulis kode Singleton. Cukup unduh Singleton.cs Base Class ini , tambahkan ke proyek Anda, dan buat singleton Anda memperluasnya:
Sekarang kelas MySingleton Anda adalah singleton, dan Anda dapat menyebutnya dengan Instance:
Berikut adalah tutorial lengkapnya: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/
sumber