2016-03-15 7 views
5

classes deriving relationsジェネリックをサポートするUnityシングルトンベースクラスを作成するには?

私のプロジェクトでは、画像に示すようなクラス構造を持っています。

緑のクラスは非常によく走る古いコード、です。赤いボックスのクラスは新しく追加されたコードです。コンパイラエラーはありませんが、Unityでクリックを再生して新しいコードを実行すると、3つのクラスを正しく初期化できません。

ユニティコンソールでは、「DataMgrBase`2というクラスは一般的です。一般的なMonoBehavioursはサポートされていません!UnityEngine.GameObject:AddComponent()」という行があります: "instance = obj.AddComponent(); "

どうすればこの問題を解決できますか?続き

は、おかげであなたの参考のためにいくつかのコードです!シングルトンベースクラスの

実装:DataMgrBaseの

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); 
     } 
    } 
} 

が実装:あなたの具体的なクラスに続いて

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

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のやり方ではないという小さな感情を持っています。とにかく問題を解決するためにcongratz! –

+0

ありがとう:) @ジェリースウィタルスキ – ArtS

0

あなたが何かをしたい

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

OPは異なるされていることをどのように? – Everts

+0

ありがとう!試してみて、それと同じ警告です。初期化は "instance = obj.AddComponent ();"でまだ失敗しました。 – ArtS

0

これは何とかそれはあなたの問題を解決されていない答えですが、問題を説明します。

MonoBehaviourは、少なくとも二つの理由のための一般的なことはできません。

1.あなたはUnity3Dエディタからインスペクタで汎用コンポーネントを追加したい想像してみてください。エンジンはこのコンポーネントのすべての型を正確に知る必要があります。この時点でコンパイルするだけでなく、宣言されていない型を持つパブリックフィールドを持つ可能性があります。インスペクタでUnitySingletonPersistentを直接割り当ててみてください。それは不可能です。

Tは仕事ができるような一般的なルックスですが、また、このエンジンでは、あなたがインスタンス化されたゲームオブジェクトのうち、いわゆるプレハブを作ることができ、そしてこのゲームオブジェクトが含まれている場合は、一般的なコンポーネントUnity3Dエンジンはいくつかの種類をサポートする必要があります AddComponent<T>を使用して

2.実際には、これは異なる種類のスクリプトを生成し、プロジェクト内で大きな混乱を招くことになります。私はあなたが私に従うことを望む

しかし、緑色でマークしたコンポーネントではなぜ機能するのですか? Unity3Dエンジンは、このコンポーネントをGameObjectに追加するときに、すべての型を知るだけです。

このすべてをサポートするには、Unity3Dエンジンの中核となる変更を行う必要があります。それはUnity3Dを完全に異なるエンジンにしています。

問題を解決するには、実行時の汎用コンポーネントを追加しないで、DataMgrBaseクラスを取り除くという方法が1つあります。したがって、各コンポーネントにロジックDataMgrBaseを実装する必要があります。

+0

共有いただきありがとうございますが、私はすでに解決しています。私の答えをチェックしてください。ジェネリック型はコンパイル後も変更されないので、実際には「ランタイム」ジェネリックではありません。 – ArtS