2014-09-24 111 views
0

的唯一實體我知道,如果我有像Unity3d,得到具體的組件類型

Component tmp = (myClass)gameObject.GetComponent<myClass>(); 

可以返回空值,或者輸入「MyClass的」的實例,如果它存在於我的具體遊戲對象。現在,讓我們假設我有一個來自給定半徑的物理球體捕獲的對象數組。我有20個遊戲對象返回。

如何創建一個例程以僅返回具有組件的遊戲對象,因此我不必一遍又一遍地編寫自己的迭代器。再次是泛型,因爲在一個領域我可能需要另一個地方。我不想爲了使可讀性變得很痛苦而全力投入類型轉換。

反饋(每西普里安的答案)

我想你的方法逐字,並沒有得到任何人的「類」,我想,即使它是一個附加組件。所以,我試着稍微修改一下例程。首先,確保一個合適的「遊戲對象」。然後從那裏,嘗試撥打GameObject's .GetComponent<T>()。但是這會導致錯誤,即使<T>與我通過獲取組件的類型相同。

public static IEnumerable<T> GetItemsAsT<T>(this object[] objects) 
     where T:class 
    { 
     GameObject gObj; 
     foreach(var obj in objects) 
     { 
      if(obj is GameObject) 
      { 
       gObj = (GameObject)obj; 
       if(gObj.GetComponent<T>() != null) 
       { 
        Debug.Log ("Found via IEnumerable"); 
        yield return gObj.GetComponent<T>(); 
       } 
      } 
     } 
     yield break; 
    } 

每輕微修訂的Ciprian的答案。

Error CS0311: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'UnityEngine.GameObject.GetComponent<T>()'. There is no implicit reference conversion from 'T' to 'UnityEngine.Component'. (CS0311) (Assembly-CSharp) 

回答

1

現在我想我理解你的問題,所以這就是爲什麼我作爲一個單獨的答案發布。

您有一個複合對象,並且您想調用基於遊戲對象中存在的自定義類「屬性」混合的自定義操作。

public static IEnumerable<T> GetItemsAsT<T>(this GameObject[] objects) 
    where T:UnityEngine.Component 
    { 
     foreach(var obj in objects) 
     { 
      var t = obj.GetComponent<T>(); 
      if(t != null) 
       yield return t; 
     } 
     yield break; 
    } 

我更新了更改並從您的答案中刪除了不需要的轉換。從這些問題的一個重要的變化是:

  • 使用遊戲對象[]數組不能用手使你蒙上

  • 使用其中T:組件,而不是T:類

+0

感謝修改後的問題,稍後將在家中嘗試,但認爲這是因爲我錯過了「where T:class」子句 – DRapp 2014-09-24 13:19:48

+0

我試過並更新了我的帖子和修改後的實現。你能看看它,看看它對你有意義嗎? – DRapp 2014-09-24 21:09:09

+0

經過反饋後更新了回覆 – 2014-09-25 07:01:57

1

我瞭解,你需要兩個代碼的情況下,可以實現對對象的數組:

static class GenericUtils 
{ 
    public static IEnumerable<T> GetItemsAsT<T>(this object[] objects) 
    where T:class 
    { 
     foreach(var obj in objects) 
     { 
      var t = obj as T; 
      if(t != null) 
       yield return t; 
     } 
     yield break; 
    } 
    public static IEnumerable<T> GetItemsWhere<T>(this object[] objects, Predicate<T> predicate) 
     where T:class 
    { 
     foreach(var tObj in objects.GetItemsAsT<T>()) 
     { 
      if(predicate(tObj)) 
      { 
       yield return tObj; 
      } 
     } 
     yield break; 
    } 
} 

要使用它們,你可以得到假設圓的清單:

items.GetItemsAsT<Circle>(); 

或使用謂詞對其進行過濾:

items.GetItemsWhere<Circle>(c => c.Radius < 30); 

所有的項目都是IEnumerable的,所以如果你需要將它們轉換爲數組,使用.ToArray(),或使用它們作爲一個列表中使用.ToList()

後來 如果您熟悉使用LINQ,你可以只使用第一種方法,後來使用Linq組合功能,使的最後一行代碼就可以改寫爲:

items.GetItemsAsT<Circle>().Where(c => c.Radius < 30); 

另外,如果你的名字GetItemsAsT是冗長的,選擇只是他們的一個較短的名稱:AST。

+0

外貌很有前途,但如果我有一個包含3個與其關聯的類別腳本的遊戲對象,那麼您如何/在哪裏確認整個遊戲對象包含我特別尋找的組件之一。如果連接了3個,我無法確認哪個「myGameObject是someClass」,我必須轉到特定的GetComponent ()以查看是否關聯,然後使用該組件部分。 – DRapp 2014-09-24 11:39:46