2016-03-15 18 views
5

classes deriving relations如何讓Unity單體基類支持泛型?

在我的項目中,我有一個類結構,如圖所示。

綠色班是舊的代碼,運行得很好。紅色框中的類是新添加的代碼。沒有編譯器錯誤,但是當單擊Unity中的播放並運行到新代碼中時,三個類無法正確初始化。

Unity控制檯給出了警告:「名爲'DataMgrBase`2'的類是通用的,不支持通用MonoBehaviours!」在這一行:「instance = obj.AddComponent(); 「

我該如何解決這個問題?

以下是一些供您參考的代碼,謝謝!

實現單基類:

using UnityEngine; 
using System.Collections; 

public class UnitySingletonPersistent<T> : MonoBehaviour where T : Component 
{ 
    private static T instance; 

    public static T Instance { 
     get { 
      if (instance == null) { 
       instance = FindObjectOfType<T>(); 
       if (instance == null) { 
        GameObject obj = new GameObject(); 
        obj.name = typeof(T).Name; 
        obj.hideFlags = HideFlags.DontSave; 
        instance = obj.AddComponent<T>(); 
       } 
      } 
      return instance; 
     } 
    } 

    public virtual void Awake() 
    { 
     DontDestroyOnLoad (this.gameObject); 
     if (instance == null) { 
      instance = this as T; 
     } else { 
      Destroy (gameObject); 
     } 
    } 
} 

DataMgrBase的執行情況:

public class DataMgrBase<TKey, TValue>: UnitySingletonPersistent<DataMgrBase<TKey, TValue>> { 

    protected Dictionary<TKey, TValue> dataDict; 

    public override void Awake() 
    { 
     base.Awake(); 

     dataDict = new Dictionary<TKey, TValue>(); 
    } 

    public TValue GetDataForKey(TKey key) 
    { 
     TValue data; 
     if (dataDict.TryGetValue(key, out data)) 
     { 
      return data; 
     } 
     else 
     { 
      data = LoadDataForKey(key); 
      if (data != null) 
      { 
       dataDict.Add(key, data); 
      } 

      return data; 
     } 
    } 

    virtual protected TValue LoadDataForKey(TKey key) 
    { 
     if (dataDict.ContainsKey(key)) 
     { 
      return GetDataForKey(key); 
     } 
     else 
     { 
      return default(TValue); 
     } 
    }  
} 

回答

1

我已經自己解決了這個問題如下:

基類的變化得到一個新的通用型(類的會從中獲得,並通過這種類型的單身基類)

public class DataMgrBase<TKey, TValue, TClass>: UnitySingletonPersistent<TClass> where TClass: Component 

對於所有那些想從中得到其他三個類別,它們更改爲以下形式:

public class MobSettingDataMgr : DataMgrBase<int, MobSettingData, MobSettingDataMgr> 
+0

這是很酷的解決方法,但是我有一點小小的感覺,那就是Unity3D的做事方式。無論如何,祝賀你解決問題! –

+0

謝謝:) @JerrySwitalski – ArtS

0

你想要的東西,如:

public abstract class UnitySingletonPersistent<T> : MonoBehaviour where T:UnitySingletonPersistent<T> 
{ 
... 
} 

然後在您的具體類:

public class DataMgrBase<TKey, TValue> : UnitySingletonPersistent<DataMgrBase<TKey, TValue> > 
{ 
... 
} 
+0

如何從OP不同? – Everts

+0

謝謝!試了一下,仍然是一樣的警告。初始化仍然失敗在「實例= obj.AddComponent ();」 – ArtS

0

這是不知何故解答您的問題,但會解釋問題。

MonoBehaviour不能至少有兩個原因是通用的:

假如你想從Unity3D編輯器中檢查添加通用組件。現在引擎需要確切地知道這個組件中的所有類型,不僅在這一刻它將被編譯,而且還會導致你可以使用未被清除類型的公共字段。嘗試直接在Inspector中指定您的UnitySingletonPersistent,並且您會看到它是不可行的。

2.使用AddComponent<T>其中T是通用貌似可以工作,而且在這個引擎,你可以讓所謂的預製件實例化出來的GameObjects,如果這個遊戲對象包含通用組件Unity3D引擎將需要支持某種的烘焙類型,實際上這會導致生成腳本,每種腳本都有不同的類型,並且在項目內部造成很大的混亂。我希望你跟着我。

但是,爲什麼它適用於您用綠色標記的組件?在將此組件添加到GameObject時,只需使Unity3D引擎知道所有類型。

爲了支持所有這些,Unity Technologies需要對Unity3D引擎進行核心更改,現在它如何工作。這將使Unity3D完全不同於現在的引擎。

所以要解決你的問題,只有一種方法:不在運行時添加通用組件,並且除掉DataMgrBase類。所以你需要在每個組件中實現DataMgrBase邏輯。

+0

感謝分享,但我已經解決了它。請檢查我的答案。通用類型在編譯後不會改變,所以它實際上不是「運行時」通用的。 – ArtS