我有一个基本问题,可以帮助新的团结伙伴更快地学习。如您所知,我们统一使用单例和类实例。我意识到了一件事情,我想确定自己在想什么。你能帮我确定吗?
在这种情况下,我会使用实例;
如果我有一个场景,并且想使用实例作为一层在脚本之间传输一些数据。我创建一个空的游戏对象,并将此代码分配为组件;
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);
}
}
}
所以,我想确定我是否走对了路?它一直有效到现在,但是将来在大多数高级情况下会出现问题吗?
答案 0 :(得分:0)
您的代码是正确的,这是在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");
}
}