如何在用户触摸游戏对象时阻止 ARCore 模型放置?

How do I block ARCore model placement when the user touches a GameObject?

免责声明:我是 Unity3D 和 ARCore 的新手,所以请多多包涵。

我在 Unity3D 中使用 ARCore 创建一个场景,用户可以在屏幕上 select 模型中 ScrollView 并使用 Google 的 ARCore 框架放置它们。

到目前为止,我已经开始工作了;用户触摸 ScrollView 中的模型(在 Panel 屏幕上显示为当前 selected 模型,因为我的计划是让 ScrollView 切换更多屏幕视图的可见性 space)。

问题是,当用户 select 模型时,ARCore 将模型放置在 ScrollView 和 selected 模型 Panel 后面的检测平面上对象(即使您第一次触摸开始滚动 ScrollView)。请参阅下文以帮助形象化。

如何让 ARCore 而不是 将对象放在 ScrollViewPanel 后面?我尝试的是向我的控制器(实际上只是 Google HelloARController)添加一组对象,我想阻止 ARCore 的 Raycast 并使用 foreach 遍历它们以查看 Raycast 是否命中集合

中的 GameObjects
Touch touch;
if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
    return;
}

//my code; above is Google's
foreach (var item in BlockingObjects) { //BlockingObjects is a List<GameObject>
    if (IsTouchInObject(FirstPersonCamera.ScreenPointToRay(touch.position), item)) {
        return;
    }
}
//end of my code; below is Google's

TrackableHit hit;
TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

IsTouchInObject 函数定义如下:

private bool IsTouchInObject(Ray ray, GameObject obj) {
    RaycastHit rch;
    Physics.Raycast (ray, out rch);
    return (rch.collider != null);
}

失败的是 rch.collider 总是 null(我知道我根本没有针对对象进行测试,我一旦我能让 Raycast 真正与 GameObject 发生碰撞,我就会担心这个)。我试过使用 Physics/Physics2DRaycastHit/RacastHit2D 并将 BoxCollider/BoxCollider2D 组件附加到我想要检测的对象继续,但我所做的一切都没有用。

(此解决方案取自 Unity3D 论坛,其中有人有类似问题,但与 AR 无关,他们自己的 3D 世界带有 2D 叠加层。我找不到该论坛 post提供参考,不好意思)。

如有任何帮助,我们将不胜感激。

EDIT/NOTE: 我现在注意到 Canvas 上有一个 Graphic Raycaster 组件,其中包含我的 ScrollViewPanel。我尝试将 Blocking Objects 设置为 Two D(同时将 Box Collider 2D 添加到 ScrollViewPanel)并将 Blocking Mask 设置为 Ignore Raycast(和其他一些东西)无济于事。这些属性的值组合是否可以做到这一点?

本着今天约会的精神:

帮助我,Whosebug...呃...Kenobi...你是我唯一的希望。

您是否尝试过使用以下方式包装 Raycast:

 if (!EventSystem.current.IsPointerOverGameObject(touch.fingerId)) {...}

https://answers.unity.com/questions/1406243/ui-in-arcore-helloar-example.html

这是我在 Whosebug 上的第一个回答,请耐心等待。我正在构建一个类似的应用程序,您可以在其中 select 来自 UI 面板的不同模型统一并将模型放置在现实世界中检测到的平面上。我能够设计出解决您遇到的问题的唯一方法是执行以下操作:

在您的 HelloARController.CS 中,初始化一个 bool 'place_model'(或您想要的任何名称)并将其设置为 false。现在您需要滚动到您在现实世界中增强模型的部分。

if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
                {
                    // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                    // world evolves.



                        var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                        // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                        // from the anchor's tracking.
                        var andyObject = Instantiate(m_andy, hit.Point, Quaternion.identity,
                            anchor.transform);

                        // Andy should look at the camera but still be flush with the plane.
                        andyObject.transform.LookAt(m_firstPersonCamera.transform);
                        andyObject.transform.rotation = Quaternion.Euler(0.0f,
                            andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

                        andyObject.AddComponent<BoxCollider>();
                        // Use a plane attachment component to maintain Andy's y-offset from the plane
                        // (occurs after anchor updates).
                        andyObject.GetComponent<PlaneAttachment>().Attach(hit.Plane);
}

将上面的代码改成这样:

if (place_model){   // changed portion
if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
                {
                    // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                    // world evolves.



                        var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                        // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                        // from the anchor's tracking.
                        var andyObject = Instantiate(m_andy, hit.Point, Quaternion.identity,
                            anchor.transform);

                        // Andy should look at the camera but still be flush with the plane.
                        andyObject.transform.LookAt(m_firstPersonCamera.transform);
                        andyObject.transform.rotation = Quaternion.Euler(0.0f,
                            andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

                        andyObject.AddComponent<BoxCollider>();
                        // Use a plane attachment component to maintain Andy's y-offset from the plane
                        // (occurs after anchor updates).
                        andyObject.GetComponent<PlaneAttachment>().Attach(hit.Plane);

place_model = false // changed portion
    }

}

现在无论如何都无法放置模型。因为将模型扩充到现实世界的脚本不是 运行,因为 bool 'place_model' 设置为 false。现在,就在您想要将模型扩充到现实世界时,您可以从面板 select 模型并将 'place_model' 布尔值设置为 true。这很简单,因为您只需要为您的按钮设置一个事件侦听器,当您单击该按钮时将 bool 设置为 true。下次您触摸跟踪平面时,您的模型会得到增强。

希望这能解决您的问题...