实施Unity Singleton的最佳方法? [英] Best way to implement Unity Singleton?

查看:162
本文介绍了实施Unity Singleton的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Unity的初学者.

I'm a beginner to Unity.

我目前正在实施Singleton.

I'm currently implementing Singleton.

我在学习时有疑问.

在标题中像标题一样实现Singleton的最佳方法是什么?

What is the best way to implement Singleton in Unity like the title?

我了解为什么要使用单例.那是.. 只创建一个对象,并在需要时使用它."

I understand why use a singleton. that is.. " To create an object once and use it whenever need it. "

我理解正确吗?

有很多实现单例的方法.这是正确的? 那么,许多方法中的哪一部分是通用的?

There are many ways to implement singletons. It's right? Then, Which part of the many methods are used in common?

我的单例代码是:

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;
        }
    }
}

如果您可以查看代码,我们将不胜感激, 但我们也要感谢一些要点.

We'd appreciate it if you could review the code, but we'd also appreciate a few key points.

我看过几个文档,但是它们变得很复杂. 我的水平很低.如果您能轻松解释它,我将不胜感激.

I have seen several documents, but they only get complicated. My level is very low. I would appreciate it if you could explain it easily.

推荐答案

以下是有关您的代码的一些说明:

Here's some remarks about your code:

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

  1. Inside getter of the Instance property you have a line of code: instance = go.AddComponent<T>(); The point about this line is that AddComponent<> will cause creation of the script's instance and then calling Awake() method. So you will create an instance of your sript by this line and it doesn't matter what's written in the Awake() method. So you can get rid of Awake() as it does nothing. The only case it will do some helpful work is when you'll try to create the first instance of your script (it'll just set the value of instance to the 1st instance). In other cases it's useless. So if you will create your singleton only by using Instance property - you do not need that awake.

Awake本身是MonoBehaviour脚本的类型构造器",但其执行方式有所不同.关键是,在纯c#中,您可以借助 static构造函数轻松实现单例,但是您不能在MonoBehaviour中以这种方式实现.这意味着,如果您已经有一个单例实例,并且您将尝试使用行T myNewInstance = new T();创建您的单例实例,则将实际创建第二个实例.因此,您的代码不会保护您免于直接创建实例.

Awake itself is a "kinda constructor" for MonoBehaviour scripts, but it performs differently. The point is that in pure c# you can easily implement singleton with the help of static constructor but you can't do it this way in MonoBehaviour. That means if you already have an instance of your singleton and you'll try to create your singleton instance with the line T myNewInstance = new T(); the second instance will be actually created. So your code won't protect you from direct creating of the instance.

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

Also, if you'll use gameObject.AddComponent<T>() method, your singletone code won't prevent Unity from creating new script instance.

因此,没有100%的方法在Unity中创建MonoBehaviour单调,但是有一些可能的解决方法.

So, there's no 100% method to create a MonoBehaviour singletone in Unity, but there are some possible workarounds.

例如,在此处看看.此解决方案与您的解决方案非常相似,但是它还使用了public T GetOrAddComponent<T> (this Component child) where T: Component辅助程序扩展方法,您可以借用到您的解决方案.

For example, take a look here. This solution has much similar to yours but it also uses public T GetOrAddComponent<T> (this Component child) where T: Component helper extension method, which you can borrow to your solution.

另一种可能的解决方案是,您可以创建非MonoBehaviour派生的 c#单例class 就像一个包装,用于获取MonoBehaviour类,而您只想拥有一个实例.但是您只需要使用此包装即可管理此MonoBehaviour类,否则,您将可以根据需要创建尽可能多的MonoBehaviour实例.

Another possible solution is that you can create a non-MonoBehaviour derived c# singleton class like a wrapper for getting a MonoBehaviour class, which you want to have only a single instance. But you'll have to use only this wrapper to manage this MonoBehaviour class, otherwise you will be able to create as much instances of the MonoBehaviour as you wish.

这篇关于实施Unity Singleton的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆