2016-04-01 55 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