2017-12-30 66 views
3

私はUnityでRTSゲームを作っています。私のゲームには、木、農場など、多くの種類のリソースがあります。各リソースはGameObjectであり、それを制御する主なスクリプトを持っています。ジェネリックメソッドの呼び出しは、別のジェネリックメソッド内で許可されていますか?

Ex。私は木を収穫したい、私はこれを呼ぶ。

gameObject.GetComponent<Tree>().Harvest(); 

ファームを収穫したい場合は、同じスクリプトを呼び出しますが、「ツリー」を「ファーム」に変更しても問題ありませんが、コードは複製されます。だから私はこのようなジェネリックメソッドを使って抽象化します。

void Harvest<T>(){ 
    gameObject.GetComponent<T>().Harvest(); 
} 

しかし、C#コンパイラは私にそれをさせません。ジェネリックメソッドを内部で使用するジェネリックメソッドを定義することは可能ですか?そうでなければ、このようなコードを抽象化する方法はありますか?ありがとうございました。

エラーメッセージ :

「T」「収穫」の定義なし拡張メソッド「収穫」がタイプ「T」の最初の引数を受け入れるが含まれていませんが、見つけることができる(あなたが使用して不足していますディレクティブまたはアセンブリ参照?)[アセンブリ-CSHARP]

+0

「私にそれをさせません」、あなたは確かにあなたにもっと... *特定の* ...エラーメッセージを与えませんか?例えばGetComponentに制約がありますか? –

+3

さらに、**すべて**タイプは '.Harvest'メソッドを持っていますか?それは拡張メソッドですか?さもなければ、 'Harvest'メソッド(void Harvest ()など)を提供するインターフェースを実装するTを許可するなど、自分で制約を追加する必要があります。T:IHarvestable {...' –

+0

エラーメッセージ追加されました。 @LasseVågsætherカールセン。 –

答えて

5

問題がで...

void Harvest<T>(){ 
    gameObject.GetComponent<T>().Harvest(); 
} 

... C#コンパイラがどのconcrを知っていないということですeteタイプTになります。したがって、メソッドHarvestが利用可能であること、およびその正確な宣言(それがvoidまたはboolまたはそれ以外の引数を返しますか?)を知ることはできません。 C#は厳密に型指定された言語なので、コンパイル時にこれを知る必要があります。これにより、実行時にすべてがうまくいくことが確実になります。

解決策は、コンパイラにジェネリック型制約を指定してヒントを与えることです。これを行うには、インターフェイスを宣言し、Harvestメソッドを実装したコンポーネントに実装させる必要があります。

public interface IHarvestable 
{ 
    void Harvest(); 
} 

で制約を指定します。

あなたは、基本クラスのコントロールにある他の状況で
void Harvest<T>() where T : IHarvestable 
{ 
    gameObject.GetComponent<T>().Harvest(); 
} 

、あなたもおそらく抽象として(基底クラスで必要なメソッドを宣言することができます)、インターフェイスの代わりにgeneric type constraintに基底クラスを指定します。

+0

私は何かを学んだ。ありがとうございました。 –

2

そしてTは、そのインターフェイスを拡張することを定義し、Harvest()を使用するすべてのオブジェクトのためのインタフェースを定義します。

public interface IHarvestable 
{ 
    void Harvest(); 
} 

// In your class: 
void Harvest<T>() where T: IHarvestable 
{ 
    gameObject.GetComponent<T>().Harvest(); 
} 

C#はこれをサポートしているので、単に答えを「ハック」の追加として言及BAD代替( - ません)実際にそれを使用する:あなたはdynamic使用できるチェック-timeスキップしたい場合:これは、実行時に解決メソッド呼び出しにつながる、悪い習慣です

dynamic harvestable = gameObject.GetComponent<T>(); 
harvestable.Harvest(); 

注、パフォーマンス上の欠点につながると多くのあなたのコードを作りますもっと エラーを起こしやすい。たとえば、Harvest()を実装していないTタイプのインスタンスからのメソッドの使用は、コンパイラによって許可され、実行時エラーにつながります。

+0

動的な方法を使用して面白そうに見えます。あなたは例を示すことができますか? –

+4

インターフェイスの方法を使用することをお勧めします。 –

関連する問題