簡體   English   中英

Unity3D中實例和單例之間的區別

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM