2

私はC#を使用してUnity3dゲームに取り組んでいますが、の特定のメンバー(たとえばint health)にアクセスする必要がある状況がたくさんありますGameObject。これは、次のようなコードを使用して行います。

GameObject obj;
if(obj.GetComponent<Player>() != null) {
    obj.GetComponent<Player>().health--;
}
else if(obj.GetComponent<Robot>() != null) {
    obj.GetComponent<Robot>().health--;
}
// more painful code

私がやりたいのは、そのようなすべてのクラスに、のようなインターフェースを実装させてから、を実行させるIHealthことですobj.GetComponent<IHealth>().health--;。しかし、これは可能ですか?周りを見回しましたが、型パラメーターとしてインターフェースを使用できないようです。

4

4 に答える 4

2

これを行うのは簡単ではなく、おそらく良い考えではないことがわかりました。問題はGetComponent<T>、typeパラメーターTが派生することを期待していることですComponent(もちろん、Unityはこれを文書化していません)。Robot、などをすべて、それ自体が(から)を継承し、健康やその他のフィールドに関する情報を含むPlayer抽象クラスから派生させる必要があります。これが価値があるとは思えません。他の場所でも同じくらい厄介なコードにつながる可能性があります。ComponentMonoBehaviour

于 2012-11-29T00:21:06.430 に答える
0

SLaksが指摘したように、インターフェースはジェネリック型パラメーターとして完全に受け入れられます。問題がインターフェースを介してフィールドにアクセスすることである場合は、フィールドをプロパティに変更することをお勧めします。何らかの理由でそのフィールドを絶対に保持する必要がある場合は、インターフェイスを暗黙的に実装するラッピングプロパティを指定するだけです。フィールドとプロパティの名前(大文字と小文字を含む)がまったく同じであることが問題である場合は、インターフェイスを明示的に実装できます。

public interface IHealth { int Health { get; set; } }

// Change to a property
public class Ogre : IHealth { public int Health { get; set; } }

// Casing is different, so interface can be implemented implicitly
public class Player : IHealth {
    int health;
    public int Health { get { return health; } set { health = value; } }
}

// Name collision with Pascal casing, so implement explicitly
public class Robot : IHealth {
    int Health;
    int IHealth.Health { get { return Health; } set { Health = value; } }
}

// Later
GameObject obj;
var o = obj.GetComponent<IHealth>();
if (o != null) o.Health--;
于 2012-11-28T20:54:06.093 に答える
0

消費するコードは各タイプについて知る必要があるため、基本的な設計上の問題があると思います。タイプに関係なく同じアクションを実行している場合は、古き良きポリモーフィズムを使用してください。

public class Player: IHealth {}

public class Robot: IHealth {}

一連のステートメントの代わりに、ifGetComponentからジェネリックパラメーターを削除し、IHealthオブジェクトを返すようにします。

public IHealth GetComponent()
{
    // return IHealth object here
}

呼び出しコード:

obj.GetComponent().DecreaseHealth();
于 2012-11-28T20:54:43.500 に答える
0

なぜコンポーネントだけを持っていないのですかHealth。次に、それをGameObjectにアタッチし、RequiresComponent正常性が必要なスクリプトに注釈を付けてから、それを取得しますGetComponent<Health>();(プライベート変数の同じオブジェクトスクリプト内にキャッシュします)

常に一緒になっている複数の「統計」がある場合は、次のように簡単にすることができます

public class Status : MonoBehaviour
{
    public float health;
    public float armor;
}

私は団結して見つけました、これは驚くほど一般的な「問題」です。この考え方はいくつかの問題に本当に役立つので、それが問題であるかどうかはわかりません...

于 2012-12-03T14:08:57.207 に答える