实现Unity Singleton的最佳方式是什么?

时间:2017-09-27 11:59:40

标签: c# oop unity3d singleton

我是Unity的初学者。

我目前正在实施Singleton。

我在学习期间有疑问。

在Unity中实现Singleton的最佳方式是什么?

我理解为什么要使用单身人士。那是.. "创建一个对象并在需要时使用它。 "

我能理解吗?

实现单例的方法有很多种。对不对? 然后,许多方法的哪一部分被共同使用?

我的单身代码是:

public class GameSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T instance = null;

    protected virtual void Awake()
    {
        Debug.Log ("instance was !!!!! >>" + instance);

        if(instance != null) // 최초 instance 유효성 검사
        {
            Debug.Log(">> Game Singleton already exist!");
            return;
        }

        instance = FindObjectOfType<T>(); // 
        Debug.Log("FindObj" + "/" + "instance is >> " + instance);
    }

    // Use this for initialization
    protected virtual void Start()
    {

    }

    // Update is called once per frame
    protected virtual void Update()
    {

    }

    protected virtual void OnDestroy()
    {
        if (instance != null)
        {
            instance = null;
        }
    } 

    public static T Instance
    {
        get
        {
            if(instance == null)
            {
                GameObject go = new GameObject();
                go.transform.position = Vector3.zero; // Vector3(0,0,0)
                go.transform.rotation = Quaternion.identity; // 회전 없음
                go.transform.localScale = Vector3.one;
                go.hideFlags = HideFlags.HideAndDontSave;
                instance = go.AddComponent<T>();
                instance.name = (typeof(T)).ToString();
                Debug.Log(">> Game Singleton instance create : " + instance);
            }
            return instance;
        }
    }
}

如果您可以查看代码我们很感激, 但我们也很欣赏一些关键点。

我见过几个文件,但它们只是变得复杂。 我的水平非常低。如果你能轻易解释,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

以下是关于您的代码的一些评论:

  1. Instance属性的getter内部有一行代码: instance = go.AddComponent<T>(); 关于这一行的要点是AddComponent<>将导致创建脚本的实例,然后调用Awake()方法。因此,您将通过此行创建您的sript实例,并且Awake()方法中的内容并不重要。所以你可以摆脱Awake(),因为它什么都不做。它将做一些有用的工作的唯一情况是当你尝试创建脚本的第一个实例时(它只是将实例的值设置为第一个实例)。在其他情况下,它没用。因此,如果您只使用Instance属性创建单身人士 - 则不需要清醒。

  2. Awake本身就是一个&#34;有点构造函数&#34;对于MonoBehaviour脚本,但它的表现不同。关键是在纯c#中你可以在静态构造函数的帮助下轻松实现单例,但是你不能在MonoBehaviour中这样做。这意味着如果您已经拥有单例的实例,并且您将尝试使用行T myNewInstance = new T();创建单例实例,则实际将创建第二个实例。因此,您的代码不会保护您免受直接创建实例的影响。

  3. 此外,如果您使用gameObject.AddComponent<T>()方法,则单线代码不会阻止Unity创建新的脚本实例。

  4. 所以,在Unity中没有100%的方法来创建MonoBehaviour单线,但是有一些可能的解决方法。

    例如,看看here。此解决方案与您的解决方案非常相似,但它也使用public T GetOrAddComponent<T> (this Component child) where T: Component帮助程序扩展方法,您可以借用该解决方案。

    另一种可能的解决方案是,您可以创建一个非MonoBehaviour派生c# singleton class,就像获取MonoBehaviour类的包装器一样,您希望只有一个实例。但是你必须只使用这个包装来管理这个MonoBehaviour类,否则你将能够创建尽可能多的MonoBehaviour实例。

答案 1 :(得分:1)

有很多单例模式实现可用,但Unity环境与其他环境完全不同,因此实现与其他环境完全不同。

所以在统一中你应该做更多的事情,例如你应该为你的单例对象制作一个预加载场景并将它们作为组件放在场景中。

但您可以从Game Programming Patterns - SingletonWikipedia - Singleton Pattern

了解基础知识和基础知识

以下是Unity中单例模式的一些实现:

UnityGeek - Singleton

Unity Official Wiki - Singleton

最佳实施是Unity Community - Singleton