[英]Difference between instance and singleton in Unity3D
我有一個基本的問題,可以幫助新的團結伙伴更快地學習。 如您所知,我們統一使用單例和類實例。 我意識到了一件事情,我想確定自己在想什么。 你能幫我確定嗎?
在這種情況下,我會使用實例;
如果我有一個場景,並且想使用實例作為圖層在腳本之間傳輸一些數據。 我創建一個空的游戲對象,並將此代碼分配為組件。
public class GameplayController : MonoBehaviour
{
public static GameplayController instance;
void Awake()
{
MakeInstance();
}
void MakeInstance()
{
if (instance == null)
{
instance = this;
}
else if(instance != null)
{
Destroy(gameObject);
}
}
}
在這種情況下,我會使用單例。
如果我有一個場景,並且想使用單例模式作為圖層在所有場景之間傳輸某些數據。 我創建一個空的游戲對象,並將此代碼分配為組件。
public class GameplayController : MonoBehaviour
{
public static GameplayController instance;
void Awake()
{
MakeSingleton();
void MakeSingleton()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if(instance != null)
{
Destroy(gameObject);
}
}
}
所以,我想確定我是否走對了路? 它一直有效到現在,但是將來在大多數高級情況下會出現問題嗎?
您的代碼是正確的,這是在Unity中創建單例的基本方法。
當您談到Instance vs Singleton時,我得到的一些震動可能使您可能無法理解這個概念:Singleton的想法是對象只有一個(單個)實例。
因此,您具有靜態屬性; 類的static修飾符使其無法通過new
關鍵字進行持久化。 當您將其添加到屬性中時(就像您已經做過的那樣),這意味着您可以從任何地方訪問它,而無需實例化包含類。
GameplayController.instance
在您的MakeInstance()中,驗證該實例尚未分配給實例,然后將其設置為該實例。
為了進一步遵循Singleton模式,您可能需要確保在加載新場景時不會破壞對象:
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = this;
}
將來應該不會有任何問題。 Singleton模式是一種不好的模式,但是它在原型制作中很有用。 這很簡單。
您可能遇到的問題是您的代碼將依賴於Singleton類,如果您忘記將類添加到場景中,或者如果您在較早的場景中實例化了這些類,則必須啟動該場景,這將導致錯誤。首先在調試時等
我個人使用Singleton類進行擴展,以確保在所有Singleton中具有相同的功能,並減少每個Singleton類中的膨脹,等等:
using UnityEngine;
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
private static object _lock = new object();
public static T Instance
{
get
{
if (applicationIsQuitting)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed on application quit." +
" Won't create again - returning null.");
return null;
}
lock (_lock)
{
if (_instance == null)
{
var instances = FindObjectsOfType<T>();
if (instances.Length > 1)
{
Debug.LogError("[Singleton] Something went really wrong " +
", there are too many Singletons; deleting them: ");
for (int i = 1; i < instances.Length; i++)
{
Debug.LogError("Deleting " + instances[i].gameObject.name);
Destroy(instances[i].gameObject);
}
_instance = FindObjectOfType<T>();
return _instance;
}
if (instances.Length > 0)
_instance = instances[0];
if (_instance == null)
{
GameObject singleton = new GameObject();
_instance = singleton.AddComponent<T>();
singleton.name = "[Singleton] " + typeof(T).ToString();
DontDestroyOnLoad(singleton);
Debug.Log("[Singleton] An instance of " + typeof(T) +
" is needed in the scene, so '" + singleton +
"' was created with DontDestroyOnLoad.");
}
}
return _instance;
}
}
}
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
/// <summary>
/// When Unity quits, it destroys objects in a random order.
/// In principle, a Singleton is only destroyed when application quits.
/// If any script calls Instance after it have been destroyed,
/// it will create a buggy ghost object that will stay on the Editor scene
/// even after stopping playing the Application. Really bad!
/// So, this was made to be sure we're not creating that buggy ghost object.
/// </summary>
private static bool applicationIsQuitting = false;
public void OnDestroy()
{
applicationIsQuitting = true;
}
}
然后使用如下:
public class MySingleton : Singleton<MySingleton>
{
// Don't use the Awake method, Singleton uses it to initialize
void Start() {
Debug.Log("I'm a Singleton, access me through MySingleton.Instance");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.