Unityで、これらの値をプルするすべてのクラスに同じ定数値を吐く静的変数を持つグローバルクラスとしてどこからでもアクセスできるシングルトンゲームマネージャーを作成する良い方法は何ですか?そしてそれをUnityに実装する方法は何でしょうか?ゲームオブジェクトにアタッチする必要がありますか?視覚的にシーン内に存在せずに、フォルダ内に存在することはできますか?
いつものように:状況によって異なります。私は両方の種類のシングルトン、GameObject
に接続されたコンポーネント、およびMonoBehaviour
から派生していないスタンドアロンクラスを使用しています。 IMO全体的な問題は、インスタンスがシーン、ゲームオブジェクトのライフサイクルにどのようにバインドされるかということです。また、他のMonoBehaviour
オブジェクトを特に参照するコンポーネントを使用する方が簡単で安全であることを忘れないでください。
Start
が呼び出されるか、Update
または他のメソッドでアクションを実行する必要があります。次に、それらをコンポーネントとして実装し、新しいシーンのロード後も存続するゲームオブジェクトにアタッチします。私は2つの部分を持つコンポーネントベースのシングルトン(タイプ2)を設計しました:GameObject
と呼ばれる永続的なMain
はすべてのコンポーネントを保持し、MainComponentManager
と呼ばれるフラットシングルトン(タイプ1)を管理用にそれ。いくつかのデモコード:
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に慣れていないエンジニアは、多くの場合、それに気付かない
無意味です。
Unityにあるのは、XYZの位置にあるGameObjectsだけです。コンポーネントを取り付けることができます。
.... PhotoshopまたはMicrosoft Wordで「シングルトン」または「継承」を実現しようとするようなものです。
Photoshopファイル-XY位置のピクセル
テキストエディターファイル-X位置の文字
Unityファイル-XYZ位置のゲームオブジェクト
それは「ただそれだけ」です。
信じられないほど簡単なハウツー: https://stackoverflow.com/a/35891919/294884
それはとても簡単で、問題ではありません。
Unityに「組み込みのプリロードシーン」が含まれると(つまり、ワンクリックでシーンを作成できるようにするため)、これについては最終的に再び議論されることはありません。
(注A-Unityのコンポーネントのコンパイルに使用する一部の言語にはもちろんOOの概念があります。Unity自体はOOとはまったく関係がありません。)
(注B-Unityの初期の頃は、「オンザフライでゲームオブジェクトを作成し、それを一意に保ち、それにアタッチする」というコードを作成しようとする試みが見られます(奇妙なことは別として、FWIWだけでは理論的に一意性を保証することはできません(実際にはフレーム内でさえも不可能です)。繰り返しますが、それは些細な問題ではないため、完全にモットーではありません。 )
シングルトンオブジェクトを簡単に作成できるシングルトンクラスを作成しました。これはMonoBehaviourスクリプトなので、コルーチンを使用できます。これは nity Wiki記事 に基づいており、後でプレハブから作成するオプションを追加します。
そのため、シングルトンコードを記述する必要はありません。 this Singleton.cs Base Class をダウンロードしてプロジェクトに追加し、それを拡張するシングルトンを作成します。
public class MySingleton : Singleton<MySingleton> {
protected MySingleton () {} // Protect the constructor!
public string globalVar;
void Awake () {
Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID());
}
}
これで、MySingletonクラスはシングルトンになり、インスタンスによって呼び出すことができます。
MySingleton.Instance.globalVar = "A";
Debug.Log ("globalVar: " + MySingleton.Instance.globalVar);
これが完全なチュートリアルです: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/
このクラスがグローバル変数へのアクセスのみを目的としている場合は、これにシングルトンパターンを実際に必要としたり、GameObjectを使用したりする必要はありません。
パブリック静的メンバーを持つクラスを作成するだけです。
public class Globals
{
public static int mStatic1 = 0;
public static float mStatic2 = 0.0f;
// ....etc
}
他のソリューションは問題ありませんが、必要なのが変数へのグローバルアクセスだけである場合は、やりすぎです。
クラスごとに1つのシングルトンを作成する代わりに。シングルトンのジェネリッククラスを作成することをお勧めします。私はこの方法を使用して私の人生をとても簡単にしています。
詳細については こちら をご覧ください
または
UnityでUnity C#クラスを作成し、次のコードを使用します
/// <summary>
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton<MyClassName> {}
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static T Instance
{
get
{
if (m_ShuttingDown)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed. Returning null.");
return null;
}
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
これは私が作成したセットアップです。
最初にこのスクリプトを作成します。
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;
}
}
次に、シングルトンになりたいクラスでこれを行います:
public class ExampleManager : MonoBehaviour
{
static public ExampleManager sharedManager
{
get
{
return MonoBehaviourUtility.GetManager<ExampleManager>( ref _sharedManager );
}
}
static private ExampleManager _sharedManager;
}
Unityチュートリアルから取った簡単なコードを次に示します。よりよく理解するために link を開いてください
using System.Collections.Generic; //Allows us to use Lists.
public class GameManager : MonoBehaviour
{
public static GameManager instance = null; //Static instance of GameManager which allows it to be accessed by any other script.
private BoardManager boardScript; //Store a reference to our BoardManager which will set up the level.
private int level = 3; //Current level number, expressed in game as "Day 1".
//Awake is always called before any Start functions
void Awake()
{
//Check if instance already exists
if (instance == null)
//if not, set instance to this
instance = this;
//If instance already exists and it's not this:
else if (instance != this)
//Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
Destroy(gameObject);
//Sets this to not be destroyed when reloading scene
DontDestroyOnLoad(gameObject);
//Get a component reference to the attached BoardManager script
boardScript = GetComponent<BoardManager>();
//Call the InitGame function to initialize the first level
InitGame();
}
//Initializes the game for each level.
void InitGame()
{
//Call the SetupScene function of the BoardManager script, pass it current level number.
boardScript.SetupScene(level);
}
//Update is called every frame.
void Update()
{
}