2016-04-01 52 views
2

我正在嘗試使用Singleton模式來監視Unity項目上的統計信息。我正在使用下面的類。我遇到的問題是,似乎代替只有一個單例,我的代碼爲我稱之爲單例函數的每個實例創建一個單例。例如,每次玩家開槍時我都會打電話給ShootingStats.Instance.incrementTotalShotsFired();。如果我總共有三名玩家,我的代碼似乎會產生三個ShootingStats singeton - 每個玩家一個。我想要達到的目標只有一個班級來監測所有球員的統計數據,而不是每個球員的統計數據。 我找到了單身代碼:http://wiki.unity3d.com/index.php/Singleton。我是Unity新手,但在編程方面頗有經驗。我最初嘗試使用一個非常簡單的Singleton模式版本,因爲有人會在C#中使用它,但它沒有按預期工作。相反,每次我訪問其中一個單例方法時,它都會創建一個新對象。非常感謝您的幫助。Singleton Pattern Unity創建多個副本

Singleton類

using UnityEngine; 

/// <summary> 
/// Be aware this will not prevent a non singleton constructor 
/// such as `T myT = new T();` 
/// To prevent that, add `protected T() {}` to your singleton class. 
/// 
/// As a note, this is made as MonoBehaviour because we need Coroutines. 
/// </summary> 
namespace Porject.Statistics 
{ 
    public 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) 
        { 
         _instance = (T)FindObjectOfType(typeof(T)); 

         if (FindObjectsOfType(typeof(T)).Length > 1) 
         { 
          //Debug.LogError("[Singleton] Something went really wrong " + 
          // " - there should never be more than 1 singleton!" + 
          // " Reopening the scene might fix it."); 
          return _instance; 
         } 

         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."); 
         } 
         else 
         { 
          //Debug.Log("[Singleton] Using instance already created: " + 
          // _instance.gameObject.name); 
         } 
        } 

        return _instance; 
       } 
      } 
     } 

     private static bool applicationIsQuitting = false; 

     /// <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> 
     public void OnDestroy() 
     { 
      applicationIsQuitting = true; 
     } 
    } 
} 

ShootingStats類

using UnityEngine; 
using System.Collections; 
using Project.Statistics; 

namespace Project.Statistics 
{ 
    public class ShootingStats : Singleton<ShootingStats> 
    { 

     private int _onTarget = 0; 
     private int _totalShotsFired = 0; 

     protected ShootingStats() { } 

     public void incrementOnTarget() 
     { 
      _onTarget++; 
     } 

     public void incrementTotalShotsFired() 
     { 
      _totalShotsFired++; 
     } 

     public void printStats() 
     { 
      string lines = "Total shots fired: " + _totalShotsFired + "\n" + "Shots on target: " + _onTarget + "\n."; 
      Debug.Log(lines); 
     } 
    } 
} 

MethodExtensionForMonoBehaviourTransform級 - 不完全相信這是什麼

using UnityEngine; 

static public class MethodExtensionForMonoBehaviourTransform 
{ 
    /// <summary> 
    /// Gets or add a component. Usage example: 
    /// BoxCollider boxCollider = transform.GetOrAddComponent<BoxCollider>(); 
    /// </summary> 
    static public T GetOrAddComponent<T>(this Component child) where T : Component 
    { 
     T result = child.GetComponent<T>(); 
     if (result == null) 
     { 
      result = child.gameObject.AddComponent<T>(); 
     } 
     return result; 
    } 
} 
+0

我很抱歉,但您的評論不以任何方式幫助。什麼應該是靜態的,爲什麼?我調用獲取實例的方法是靜態的。一些更多的解釋,將不勝感激 – Soc

回答

4

人就可以實現Singleton模式的行爲對遊戲物體在一個更簡單的方法:

private static GameControllerBehaviour instance; 

void Awake(){ 

    //SINGLETON PATTERN 

    if (GameControllerBehaviour.instance == null){ 
     DontDestroyOnLoad (this); 
     GameControllerBehaviour.instance = this; 

    } else { 
     Destroy (this.gameObject); 
    } 
} 
+0

好的答案。很簡單。 – Programmer

+0

嗨,謝謝你的回覆。這不適用於我的代碼。 Awake()函數永遠不會被調用。另外,我需要類似Singleton的項目在整個生命週期內持續。我怎樣才能做到這一點? – Soc