【问题标题】:Unity: Object is not being detected by raycast for highlightingUnity:光线投射未检测到对象以突出显示
【发布时间】:2013-12-24 05:58:26
【问题描述】:

我在对象选择上关注了这个tutorial。但是,当我导入我的 .obj 资产并尝试选择/突出显示它们时,光线投射器似乎没有拾取它们。当我的鼠标点击我的 .obj 对象时,什么也没有发生。我添加了必要的对撞机(盒子对撞机甚至网格对撞机),但没有任何反应。

我做错了什么?

我没有更改提供的源代码。我刚刚将我的目标文件导入场景并添加了必要的物理。

我要做的就是通过onMouseDown 突出显示我的.obj 文件。

AppRoot.cs:

using UnityEngine;
using System;

public class TransformObject
{
    ///////////////////////////////////////////////////////////////////////////
    #region Variables

    // variables

    #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER
    private float RotationSpeed = 1500;
    private float MoveSpeed = 50.0f;
    private float ZoomSpeed = 15.3f;
    #endif // UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER

    public float MinDist = 2.0f;
    public float MaxDist = 50.0f;

    private Transform mMoveObject = null;

    #endregion
    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////
    #region Public methods

    /// <summary>
    /// 
    /// </summary>
    public TransformObject()
    {
        EnabledMoving = true;
    }

    /// <summary>
    /// Sets transform that will be used as "center" of the rotate / pan / zoom
    /// </summary>
    public void SetTransformRotateAround(Transform goMove)
    {
        mMoveObject = goMove;
        if (mMoveObject == null)
        {
            Debug.LogWarning("Error! Cannot find object!");
            return;
        }
    }

    public void Update()
    {
        if (!EnabledMoving)
        {
            return;
        }

        Vector3 dir = mMoveObject.position - Camera.main.transform.position;
        float dist = Math.Abs(dir.magnitude);

        Vector3 camDir = Camera.main.transform.forward;
        Vector3 camLeft = Vector3.Cross(camDir, Vector3.down);
        Vector3 camDown = Vector3.Cross(camDir, camLeft);
        //Vector3 camUp = Vector3.Cross(camLeft, camDir);

    #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER

        float dx = Input.GetAxis("Mouse X");
        float dy = Input.GetAxis("Mouse Y");

        // rotate
        if (Input.GetMouseButton(0))
        {
            mMoveObject.Rotate(camLeft, dy * RotationSpeed * Time.deltaTime, Space.World);
            mMoveObject.Rotate(Vector3.down, dx * RotationSpeed * Time.deltaTime, Space.Self);
        }

        // move
        if (Input.GetMouseButton(1))
        {
            Vector3 camPos = Camera.main.transform.position;
            camPos += -camLeft * MoveSpeed * dx * Time.deltaTime;
            camPos += -camDown * MoveSpeed * dy * Time.deltaTime;
            Camera.main.transform.position = camPos;
        }

        // zoom
        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            if (dist > MinDist)
            {
                mMoveObject.Translate(-dir * ZoomSpeed * Time.deltaTime, Space.World);
            }
        }

        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            if (dist < MaxDist)
            {
                mMoveObject.Translate(dir * ZoomSpeed * Time.deltaTime, Space.World);
            }
        }

    #endif // UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER
    }
    #endregion
    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////
    #region Properties
    /// <summary>
    /// Gets or set value indicating if transformation is enabled
    /// </summary>
    public bool EnabledMoving
    {
        get;
        set;
    }

    /// <summary>
    /// Gets game object that moves around
    /// </summary>
    public Transform MoveObject
    {
        get
        {
            return mMoveObject;
        }
    }

    #endregion
    ///////////////////////////////////////////////////////////////////////////
}

TransformObject.cs

using UnityEngine;
using System;

public class TransformObject
{
    ///////////////////////////////////////////////////////////////////////////
    #region Variables

    // variables

    #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER
    private float RotationSpeed = 1500;
    private float MoveSpeed = 50.0f;
    private float ZoomSpeed = 15.3f;
    #endif // UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER

    public float MinDist = 2.0f;
    public float MaxDist = 50.0f;

    private Transform mMoveObject = null;

    #endregion
    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////
    #region Public methods

    /// <summary>
    /// 
    /// </summary>
    public TransformObject()
    {
        EnabledMoving = true;
    }

    /// <summary>
    /// Sets transform that will be used as "center" of the rotate / pan / zoom
    /// </summary>
    public void SetTransformRotateAround(Transform goMove)
    {
        mMoveObject = goMove;
        if (mMoveObject == null)
        {
            Debug.LogWarning("Error! Cannot find object!");
            return;
        }
    }

    public void Update()
    {
        if (!EnabledMoving)
        {
            return;
        }

        Vector3 dir = mMoveObject.position - Camera.main.transform.position;
        float dist = Math.Abs(dir.magnitude);

        Vector3 camDir = Camera.main.transform.forward;
        Vector3 camLeft = Vector3.Cross(camDir, Vector3.down);
        Vector3 camDown = Vector3.Cross(camDir, camLeft);
        //Vector3 camUp = Vector3.Cross(camLeft, camDir);

    #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER

        float dx = Input.GetAxis("Mouse X");
        float dy = Input.GetAxis("Mouse Y");

        // rotate
        if (Input.GetMouseButton(0))
        {
            mMoveObject.Rotate(camLeft, dy * RotationSpeed * Time.deltaTime, Space.World);
            mMoveObject.Rotate(Vector3.down, dx * RotationSpeed * Time.deltaTime, Space.Self);
        }

        // move
        if (Input.GetMouseButton(1))
        {
            Vector3 camPos = Camera.main.transform.position;
            camPos += -camLeft * MoveSpeed * dx * Time.deltaTime;
            camPos += -camDown * MoveSpeed * dy * Time.deltaTime;
            Camera.main.transform.position = camPos;
        }

        // zoom
        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            if (dist > MinDist)
            {
                mMoveObject.Translate(-dir * ZoomSpeed * Time.deltaTime, Space.World);
            }
        }

        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            if (dist < MaxDist)
            {
                mMoveObject.Translate(dir * ZoomSpeed * Time.deltaTime, Space.World);
            }
        }

    #endif // UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER
    }
    #endregion
    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////
    #region Properties
    /// <summary>
    /// Gets or set value indicating if transformation is enabled
    /// </summary>
    public bool EnabledMoving
    {
        get;
        set;
    }

    /// <summary>
    /// Gets game object that moves around
    /// </summary>
    public Transform MoveObject
    {
        get
        {
            return mMoveObject;
        }
    }

    #endregion
    ///////////////////////////////////////////////////////////////////////////
}

常量.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Constants
{
    public const float cMaxRayCastDistance = 1000.0f;
}

【问题讨论】:

  • 向我们展示您的代码,我们不知道您是否完美地关注了该博客。也不会有很多人想去那个网站,下载项目,解压项目,导入项目,然后在自己的机器上调试。
  • 对于便便和咯咯笑声,请遵循 Xerosigma 的调试建议,并将您的 cMaxRayCastDistance 更改为较大的值,例如 Mathf.Infinity。我们不妨排除距离问题。
  • 我是这个博客的作者,我也尝试过导入 *.obj 文件,它工作正常。请把你的 Unity3d 项目给我,我可以帮你。
  • Denis Potapenko,我应该将项目文件发送到哪里?我可以使用什么电子邮件?
  • Jerdak,它说,“名称‘Mathf’在当前上下文中不存在。(错误 CS0103)。

标签: c# unity3d selection .obj


【解决方案1】:

这可能是由多种原因造成的,但这里有一些需要检查的地方。

  • 确保您的游戏对象附加了一个碰撞器组件。
  • 确保 GameObjects 层未设置为 Ignore Raycast。
  • 确保从正确的相机进行光线投射。

本教程似乎为 Raycast 使用默认相机,请确保场景中有一个相机,其标签设置为主相机。

【讨论】:

  • 如何确保游戏对象层没有设置为忽略光线投射?
  • 在检查器中,当您选择对象时,您应该会看到一个包含下拉列表的图层控件。确保它没有设置为忽略光线投射。 Unity手册:docs.unity3d.com/Documentation/Manual/Inspector.html
  • 它没有设置为忽略,我的对象有一个对撞机。如何确认我正在从我的主摄像头进行光线投射?
  • 光线应该来自 Camera.main。如果您按照教程进行操作,则应该已经将其设置为。只需确保您的相机标签设置为主相机,当您选择相机时,您可以在检查器中看到这一点。
  • @KalaJ 尝试 Debug.LogWarning(rayCastedGO.name);就在这一行下面: GameObject rayCastedGO = hit.collider.gameObject;如果你没有看到你的对象的名字出现,它没有被 Raycast 击中。
【解决方案2】:

我在具有三个立方体(房间 0 到房间 2)和一个平面(平面)的场景中使用了您的代码,并且效果很好。

但是你的代码有点奇怪,特别是 TransformObject 类。这个类应该是一个 MonoBehaviour(一个脚本)并且作为一个 Component 添加到与您的 AppRoot 相同的 GameObject脚本。

您甚至可以通过在您的 AppRoot 类上使用 RequireComponentAttribute 使其自动化。

那么,为什么您的代码在您的情况下不起作用?

  • 您是否尝试在运行代码时使用调试器来查看 SelectObjectByMousePos()SelectedObject 是否被调用?
  • 您想要使用的材质可能不适用于您的网格:尝试使用带有立方体的脚本(就像我一样)而不是您的 .obj
  • 重写您的代码,使 TransformObject 成为 MonoBehaviour 脚本。
  • 检查碰撞矩阵,可能某些层到层的碰撞检测被禁用。

编辑:光线投射是否适用于非凸对撞机?

【讨论】:

  • Kryptos,嗨,这确实很有趣。我导入了一个基本立方体并为其提供了与示例中相同的材料。我点击它,光线投射器检测到了立方体!立方体被选中就好了。但是,对于 .obj 文件,raycaster 仍然无法检测到它。这很有趣。
  • 我有一个猜测。您是否在 .obj Mesh 上放置了 MeshCollider?再试一次凸对撞机。有可能只有凸对撞机才能捕捉到光线投射!
  • 出于好奇,如何将代码重写为 MonoBehaviour 脚本?
  • 很简单,你的类必须继承自 MonoBehaviour。然后你只需将它作为一个组件添加到你的 GameObject 中。
【解决方案3】:

原因是“femur_left_1_7_dist/default”和“femur_left_1_7_prox/default”没有碰撞器。所以有两种方法可以解决这个问题:

  1. 在项目视图中选择“femur_left_1_7_dist”和“femur_left_1_7_prox”,并在检查器中的导入设置中选择“生成碰撞器”并按“应用”按钮:


  2. 在场景中选择“femur_left_1_7_dist/default”并按下“Component/Physics/Box Collider”;在这里查看结果:https://dl.dropboxusercontent.com/u/20023505/stackoverflow_forum/s_fix.zip

【讨论】:

  • 我去看看。出于某种原因,我以为我在对象上添加了一个网格对撞机。
  • KalaJ,好的。请让我知道你的结果。
  • 谢谢。这就是问题所在。我不知道我必须设置“生成对撞机”,即使我向对象添加了一个盒子对撞机。
  • 丹尼斯,我还有一个问题。当我尝试将此项目的场景导入我的另一个项目时,我收到以下错误,我不确定为什么:NullReferenceException: Object reference not set to an instance of an object.
  • KalaJ,对于在另一个项目中使用场景,您不能只是复制它,因为这样项目会丢失对场景对象的所有引用,这可能会导致此类错误。您应该在资产中创建一个空预制件,然后将场景中的所有对象移动到此预制件,然后只需按“导出包”。最后,将此包导入另一个项目。如果您仍然不明白如何导出和导入包,请告诉我,我会为您创建包,并给您一个链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2016-04-22
  • 1970-01-01
相关资源
最近更新 更多