Unity单身经理类

在Unity中,创build一个单例游戏pipe理器的好方法是什么,它可以作为一个全局类来访问,这个静态variables会向每个拉动这些值的类都吐出相同的常量值? 那么在Unity中实现它的方法是什么? 我必须把它附加到一个游戏对象? 它可以只是在一个文件夹中,而不是在视觉上在场景中?

像往常一样:这取决于。 我使用了两种types的单例,连接到GameObject组件和不是从MonoBehaviour派生的独立类。 海事组织的整体问题是如何实例绑定到场景,游戏对象的生命周期……不要忘记有时组件特别是引用其他MonoBehaviour对象更容易和更安全。

  1. 有些类只需要提供一些值,例如一个configuration类,当调用时需要从持久层加载设置。 我将这些类devise成简单的单例。
  2. 另一方面,一些对象需要知道什么时候开始了一个场景,也就是Start被调用,或者必须在Update或其他方法中执行动作。 然后,我将它们作为组件实现,并将它们附加到一个可以存储新场景的游戏对象上。

我devise了基于组件的单件(types2),它由两部分组成:一个叫做Main的持久化GameObject ,它包含所有组件和一个名为MainComponentManager的平面单体(types1)来pipe理它。 一些演示代码:

 public class MainComponentManger { private static MainComponentManger instance; public static void CreateInstance () { if (instance == null) { instance = new MainComponentManger (); GameObject go = GameObject.Find ("Main"); if (go == null) { go = new GameObject ("Main"); instance.main = go; // important: make game object persistent: Object.DontDestroyOnLoad (go); } // trigger instantiation of other singletons Component c = MenuManager.SharedInstance; // ... } } GameObject main; public static MainComponentManger SharedInstance { get { if (instance == null) { CreateInstance (); } return instance; } } public static T AddMainComponent <T> () where T : UnityEngine.Component { T t = SharedInstance.main.GetComponent<T> (); if (t != null) { return t; } return SharedInstance.main.AddComponent <T> (); } 

现在想要注册为Main组件的其他单例只是如下所示:

 public class AudioManager : MonoBehaviour { private static AudioManager instance = null; public static AudioManager SharedInstance { get { if (instance == null) { instance = MainComponentManger.AddMainComponent<AudioManager> (); } return instance; } } 

对Unity不熟悉的工程师往往不会注意到这一点

你不能在ECS系统中拥有“单身人士”。

这是没有意义的。

你在Unity所拥有的就是GameObjects,在XYZ的位置。 他们可以有组件连接。

这将像在Photoshop或Microsoft Word中尝试“单身”或“inheritance”一样。

Photoshop文件 – 在XY位置的像素
文本编辑器文件 – X位置的字母
Unity文件 – 在XYZ位置的GameObjects

这是“这么简单”。

当然,在每个Unity项目中,你绝对必须有一个预加载场景。

令人难以置信的简单操作方法: https : //stackoverflow.com/a/35891919/294884

这很简单,这是一个非问题。

一旦Unity包含一个“内置的预载场景”(即为了节省您一键创build),这将永远不会再被讨论。

(注意 – 你用来编译 Unity 组件的一些语言当然有OO的概念; Unity本身根本就没有OO的连接。)

(注意B – 在Unity的早期,你会看到一些代码的创build ,它们“创造一个游戏对象,并且保持独特 – 并且将它自己附加到它上面” 。除了怪异之外,FWIW理论上不是有可能确保唯一性(实际上甚至不在一个框架内)。同样,这完全没有意义,因为这是一个微不足道的问题,在Unity的一般行为就是在预载场景中。

如果这个类只是为了访问全局variables,那么你并不需要一个单例模式,或者使用一个GameObject。

只需使用公共静态成员创build一个类。

 public class Globals { public static int mStatic1 = 0; public static float mStatic2 = 0.0f; // ....etc } 

其他的解决scheme是好的,但如果你需要的是全局访问variables,那就太过分了。

我写了一个单例类,可以很容易地创build单例对象。 它是一个MonoBehaviour脚本,所以你可以使用协程。 它基于这个Unity Wiki文章 ,我将添加选项来从Prefab中创build它。

所以你不需要写Singleton代码。 只需下载这个Singleton.cs基类 ,将其添加到您的项目,并创build您的单例扩展它:

 public class MySingleton : Singleton<MySingleton> { protected MySingleton () {} // Protect the constructor! public string globalVar; void Awake () { Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID()); } } 

现在你的MySingleton类是一个单例,你可以通过Instance调用它:

 MySingleton.Instance.globalVar = "A"; Debug.Log ("globalVar: " + MySingleton.Instance.globalVar); 

这是一个完整的教程: http : //www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/

这是我创build的设置。

首先创build这个脚本:

MonoBehaviourUtility.cs

 using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; static public class MonoBehaviourUtility { static public T GetManager<T>( ref T manager ) where T : MonoBehaviour { if (manager == null) { manager = (T)GameObject.FindObjectOfType( typeof( T ) ); if (manager == null) { GameObject gameObject = new GameObject( typeof( T ).ToString() ); manager = (T)gameObject.AddComponent( typeof( T ) ); } } return manager; } } 

然后在任何一个class级你想成为一个单身人士这样做:

 public class ExampleManager : MonoBehaviour { static public ExampleManager sharedManager { get { return MonoBehaviourUtility.GetManager<ExampleManager>( ref _sharedManager ); } } static private ExampleManager _sharedManager; } 

一种方法是制作一个场景来初始化你的游戏pipe理器,如下所示:

 public class GameManager : MonoBehaviour { GameManager static instance; //other codes void Awake() { DontDestroyOnLoad(transform.gameObject); instance = this; } //other codes } 

就是这样,这就是你需要做的。 然后在初始化游戏pipe理器之后,立即加载下一个场景,而不再回到这个场景。

看看这个教程: https : //youtu.be/64uOVmQ5R1k? list =WL