如何在用户触摸游戏对象时阻止 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 而不是 将对象放在 ScrollView
和 Panel
后面?我尝试的是向我的控制器(实际上只是 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
/Physics2D
和 RaycastHit
/RacastHit2D
并将 BoxCollider
/BoxCollider2D
组件附加到我想要检测的对象继续,但我所做的一切都没有用。
(此解决方案取自 Unity3D 论坛,其中有人有类似问题,但与 AR 无关,他们自己的 3D 世界带有 2D 叠加层。我找不到该论坛 post提供参考,不好意思)。
如有任何帮助,我们将不胜感激。
EDIT/NOTE: 我现在注意到 Canvas
上有一个 Graphic Raycaster
组件,其中包含我的 ScrollView
和 Panel
。我尝试将 Blocking Objects
设置为 Two D
(同时将 Box Collider 2D
添加到 ScrollView
和 Panel
)并将 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。下次您触摸跟踪平面时,您的模型会得到增强。
希望这能解决您的问题...
免责声明:我是 Unity3D 和 ARCore 的新手,所以请多多包涵。
我在 Unity3D 中使用 ARCore 创建一个场景,用户可以在屏幕上 select 模型中 ScrollView
并使用 Google 的 ARCore 框架放置它们。
到目前为止,我已经开始工作了;用户触摸 ScrollView
中的模型(在 Panel
屏幕上显示为当前 selected 模型,因为我的计划是让 ScrollView
切换更多屏幕视图的可见性 space)。
问题是,当用户 select 模型时,ARCore 将模型放置在 ScrollView
和 selected 模型 Panel
后面的检测平面上对象(即使您第一次触摸开始滚动 ScrollView
)。请参阅下文以帮助形象化。
如何让 ARCore 而不是 将对象放在 ScrollView
和 Panel
后面?我尝试的是向我的控制器(实际上只是 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
/Physics2D
和 RaycastHit
/RacastHit2D
并将 BoxCollider
/BoxCollider2D
组件附加到我想要检测的对象继续,但我所做的一切都没有用。
(此解决方案取自 Unity3D 论坛,其中有人有类似问题,但与 AR 无关,他们自己的 3D 世界带有 2D 叠加层。我找不到该论坛 post提供参考,不好意思)。
如有任何帮助,我们将不胜感激。
EDIT/NOTE: 我现在注意到 Canvas
上有一个 Graphic Raycaster
组件,其中包含我的 ScrollView
和 Panel
。我尝试将 Blocking Objects
设置为 Two D
(同时将 Box Collider 2D
添加到 ScrollView
和 Panel
)并将 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。下次您触摸跟踪平面时,您的模型会得到增强。
希望这能解决您的问题...