2014-09-24 110 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