我想知道哪种方法是使用单例实例的正确方法:当我创建一个名为“ Manager”的单例类,并且它包含一个名为“ value”的int变量,而我又有一个名为“ A”的类... / p>
//singleton class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Manager : MonoBehaviour {
public static Manager Instance{ set; get;}
public int value;
private void Awake () {
if (Instance == null) {
Instance = this;
DontDestroyOnLoad (this.gameObject);
} else {
Destroy (gameObject);
}
}
}
因此,在我的A类中,我可以像下面这样创建单例的实例: //示例伪代码 公共A级 {
// First
// using as a global variable
Manager manager;
//------------------------------------
Public void tstOne(){
// First
// using that global variable
manager.Instance.value = 0;
// Second
// or this way
Manager.Instance.value = 0;
}
Public void tstTwo(){
// First
// using that global variabl
manager.Instance.value = 1;
// Second
// or this way
Manager.Instance.value = 1;
}
}
所以我的问题是-我应该创建一个全局实例,然后像第一个实例一样使用该实例,还是应该使用第二个实例?
它们在内存消耗和效率方面是否都相同? 还是有其他使用单例的方法?
答案 0 :(得分:0)
Instance
是一个静态字段,因此您应该使用Manager.Instance
获取对单例的引用。
Manager.Instance
是可全局访问的实例,因为它是公共静态的。 C#中没有像全局变量这样的东西。
直接通过类名访问静态字段绝对比在A中将第二个实例作为字段然后使用它访问静态实例要好。
答案 1 :(得分:0)
我确认了Ruzihm的回答(我也同意derHugo的评论,我个人更喜欢SO,并在需要时引用它们。比Singleton或DI直接方法干净得多)。
要特定地访问实例成员manager.Instance.value
的速度较慢,并且还需要在堆上分配更多的内存,因此会损害内存使用率和速度性能。 (非常小的性能问题,但仍然如此。)
单身人士还有进一步的改进空间,尤其是如果您不要求它源自MonoBehaviour。
您可以:
这就是实现方式(考虑到您使用Manager
作为辅助实例,如果需要单行为逻辑,则使用YourManagerMono
:
public class YourManagerMono : MonoBehaviour
{
}
public sealed class Manager
{
private static readonly Manager instance = new Manager();
//use a gameobject to relate it in the scene
private YourManagerMono monoManager;
public static Manager Instance => instance;
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Manager() {}
private Manager()
{
//find or create a manager
monoManager = GameObject.FindWithTag("Manager").GetComponent<YourManagerMono>();
if (monoManager == null)
{
monoManager = new GameObject().AddComponent<YourManagerMono>();
monoManager.gameObject.tag = "Manager";
Object.DontDestroyOnLoad(monoManager.gameObject);
}
}
}
Jon Skeet的C#出色的article about singleton实现(我使用了实现4)。
编辑:
我再次同意derHugo(在此答案的新评论中)。我的示例用于显示有趣的预期结果并提供尽可能多的性能,但是,如果您只需要单点1和3的Monohhaviour,则可以继续使用Unify Community的generic implementation of singleton(请记住,将结束类设置为密封的,以帮助编译器。
答案 2 :(得分:0)
对于只想在一个场景中存在的Singleton,我使用:
public class SceneSingleton<T> : MonoBehaviour
where T : SceneSingleton<T>
{
static T s_instance = null;
public static T Instance
{
get
{
if (s_instance == null)
{
s_instance = Object.FindObjectOfType<T>();
}
return s_instance;
}
}
}
然后从中继承您的类,就像这样:
public class MyManager : SceneSingleton<MyManager>
如果您需要单身人士在所有场景之间保持活跃,请尝试使用以下方法:
public class GlobalSingleton<T> : MonoBehaviour
where T : GlobalSingleton<T>
{
static T s_instance = null;
public static T Instance
{
get
{
if (s_instance == null)
{
GameObject prefab = Resources.Load(typeof(T).Name) as GameObject;
if (prefab == null || prefab.GetComponent<T>() == null)
{
Debug.LogError("Prefab for game manager " + typeof(T).Name + " is not found");
}
else
{
GameObject gameManagers = GameObject.Find("GameManagers");
if (gameManagers == null)
{
gameManagers = new GameObject("GameManagers");
DontDestroyOnLoad(gameManagers);
}
GameObject gameObject = Instantiate(prefab);
gameObject.transform.parent = gameManagers.transform;
s_instance = gameObject.GetComponent<T>();
s_instance.Init();
}
}
return s_instance;
}
}
protected virtual void Init()
{ }
}