【问题标题】:How do I determine class of object at mouse position (Unity3d)如何确定鼠标位置的对象类别(Unity3d)
【发布时间】:2017-05-17 02:55:01
【问题描述】:

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

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

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

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

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

给定的表达式绝不是提供的 ('foo') 类型

上面链接中也建议的选项 2. 会产生错误

无法通过引用转换、装箱转换、拆箱转换、包装转换或空类型转换将类型“UnityEngineGameObject”转换为“foo”

选项 3. 被建议 here 并产生错误

NullReferenceException:对象引用未设置为对象的实例

这似乎是一项简单的任务,但我遇到了一些麻烦。那么,如何确定鼠标所在对象的类/类型?

非常感谢任何帮助!

【问题讨论】:

    标签: c# unity3d mouseover


    【解决方案1】:

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

    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 的优点是查找项目相当快。您还可以扩展模式的使用,使其可以与任何具有泛型的类型一起使用,但我想这已经足够了。

    【讨论】:

    • 感谢您的回答,+1。我接受了@Lincoln 的回答,因为检查无效性(你也提到过)是关键,尽管我还必须解决其他问题,他更早地回答了。干杯!
    【解决方案2】:

    你也可以给它分配一个标签然后使用

    objAtmouse.compareTag('your tag name');
    

    【讨论】:

      【解决方案3】:

      场景中的所有对象都是游戏对象本身,不会是 cild 类。您要查找的其他类将是组件

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

      【讨论】:

        【解决方案4】:

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

        Foo fooComponent = objAtMouse.GetComponent<Foo>();
        
        if (fooComponent == null) .. //no Foo component.
        

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

        【讨论】:

        • 感谢您的回复 :) 我已经尝试了您的建议,但我得到了上面列出的 NullReferenceException。我错过了什么吗?
        • NullReferenceException 出现在哪一行?你检查过objAtMouse 是不是null
        • 嗨。是的,我首先检查 objAtMouse 是否为空,并且仅在结果 if 块内对 fooComponent 进行后续测试。错误发生在运行时;有没有办法获得有关哪一行导致错误的更多详细信息?谢谢!
        • 是的,当统一控制台显示 NullReferenceException 错误消息时,您可以单击它以显示详细信息,例如发生在哪个脚本和哪一行。如果您使用的是 monodevelop 编辑器,请双击错误,它将带您进入代码行
        • 非常感谢您的提示!所以我这样做了,看起来这条线是上面的 GameObject objAtMouse = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(mousePos), Vector2.zero).transform.gameObject;但这以前有效。有什么想法吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-08
        • 2010-10-07
        • 1970-01-01
        相关资源
        最近更新 更多