2016-04-01 20 views
2

Bir Unity projesindeki istatistikleri izlemek için Singleton desenini kullanmaya çalışıyorum. Aşağıdaki sınıfları kullanıyorum. Benim sahip olduğum problem, tek bir tektona sahip olmak yerine, kodum, her bir örnek için singleton fonksiyonlarını çağırdığım bir tekil oluşturuyormuş gibi görünüyor. Örneğin, bir oyuncu silahını her ateş ettiğinde ShootingStats.Instance.incrementTotalShotsFired();'u ararım. Toplamda üç oyuncum varsa, kodum ShootingStats singeton'undan üç tane üretiyor - her oyuncu için bir tane. Kazanmak istediğim, bu istatistikleri her biri için değil, tüm oyuncular için izleyecek tek bir sınıfa sahip. Tek satırlık kodu buldum: http://wiki.unity3d.com/index.php/Singleton. Unity’de yeniyim ama programlamada oldukça tecrübeli. Başlangıçta, C# 'da kullanacağı ama istediği gibi çalışmadığı için Singleton modelinin çok basit bir sürümünü kullanmayı denedim. Bunun yerine, her zaman tekil yöntemlerden birine erişiyordum, yeni bir nesne yaratıyordu. Yardımlarınız için şimdiden çok teşekkürler.Singleton Pattern Unity birden çok kopya oluşturur

Singleton sınıf

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 sınıf

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 Sınıf - Tam olarak emin bu

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; 
    } 
} 
nedir 210
+0

Üzgünüm ama yorumunuz herhangi bir şekilde yardımcı olmuyor. Statik ne olmalı ve neden? Örnek almak için aradığım yöntem statiktir. Daha fazla açıklama, – Soc

cevap

4

Adam sen daha basit bir şekilde bir GameObject için Singleton deseni davranışını elde edebilirsiniz:

private static GameControllerBehaviour instance; 

void Awake(){ 

    //SINGLETON PATTERN 

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

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

Cevabı iyi olurdu. Çok basit. – Programmer

+0

Merhaba ve cevabınız için teşekkür ederim. Bu benim kodumda çalışmıyor. Awake() işlevi hiçbir zaman çağrılmaz. Ayrıca, projenin tüm ömrü boyunca sürmesi için Tekton'un beğenisine ihtiyacım var. Bunu nasıl yapabilirim? – Soc