如何确定鼠标位置的对象 class (Unity3d)

How do I determine class of object at mouse position (Unity3d)

我的 2D 项目中有一个 class("foo" 说),当我在鼠标位置获得对游戏对象的引用时,我想确定该对象是否属于富class。我用

获得对象
GameObject objAtMouse = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(mousePos), Vector2.zero).transform.gameObject;

其中 mousePos 是我鼠标的位置,它似乎按预期工作。为了测试 class 我尝试了以下方法:

  1. 如果(objAtMouse 是 foo){...}
  2. foo fooAtMouse = objAtMouse as foo; 如果(fooAtMouse){...}
  3. if ((objAtMouse.GetComponent("foo") as foo) != null){...}

选项 1. 被建议 here,并且是唯一一个不会产生错误但会产生警告的选项

The given expression is never of the provided ('foo') type

选项 2.,也在上面 link 中建议,产生错误

Cannot convert type 'UnityEngineGameObject' to 'foo' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion

建议选项 3 here 并产生错误

NullReferenceException: Object reference not set to an instance of an object

这似乎是一项简单的任务,但我在这方面遇到了一些麻烦。那么,如何确定我的鼠标悬停的对象的 class/type 呢?

非常感谢任何帮助!

如果 Foo 是一个组件,它可能是因为您将它附加到 GameObject,那么选项 3 非常接近。但你不需要施放它 as Foo.

Foo fooComponent = objAtMouse.GetComponent<Foo>();

if (fooComponent == null) .. //no Foo component.

请注意,您应该先检查 objAtMouse 是否为 null..

场景中的所有对象都是游戏对象本身,不会被调用class。您要查找的其他 class 是组件

所以你必须使用obj.GetComponents从游戏对象中取出它

您也可以为其分配一个标签,然后使用

objAtmouse.compareTag('your tag name');

首先,第一行无法按原样计算:

GameObject objAtMouse = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(mousePos), Vector2.zero).transform.gameObject;

这假设你有一个持续的成功命中。

Raycast2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(mousePos), Vector2.zero);
if(hit.transform != null)
{
     GameObject objAtMouse = hit.transform.gameObject;
     if(objAtMouse.GetComponent<Foo>() != null){
          // Object has component Foo on it
     }
}

另一个解决方案是让 Foo 类型讲述自己:

public class Foo:MonoBehaviour{
     private static HashSet<Transform>fooCollection;
     private void Awake()
     {
          if(fooCollection  == null)
          {
              fooCollection = new HashSet<Transform>(); 
          }
          fooCollection.Add(this.transform);
     }

     private void OnDestroy()
     {
          fooCollection.Remove(this.transform);
     }

     public static bool CompareFooObject(Transform tr)
     {
          if(tr == null) return false;
          return fooCollection.Contains(tr);
     }
}

那么您可以将其用作:

Raycast2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(mousePos), Vector2.zero);
if(Foo.CompareFooObject(hit.transform))
{
    // Is Foo type
}

HashSet的优点是查找项的速度相当快。您还可以扩展该模式的用法,以便它可以与具有泛型的任何类型一起使用,但我想现在这已经足够了。