免责声明:我对Unity3D和ARCore都很陌生,所以请耐心等待。
我在Unity3D中使用ARCore来创建一个场景,用户可以在屏幕上选择ScrollView
中的模型,并使用Google的ARCore框架放置它们。
到目前为止,我有它的工作;用户触摸ScrollView
中的模型(在Panel
屏幕上显示为当前所选模型,因为我的计划是让ScrollView
切换可见性以获得更多屏幕视图空间)。
问题是,当用户选择模型时,ARCore将模型放置在ScrollView
和所选模型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覆盖。我找不到该论坛帖子提供参考,对不起)。
任何帮助将不胜感激。
编辑/注意:我现在注意到Graphic Raycaster
上有一个Canvas
组件,其中包含我的ScrollView
和Panel
。我已经尝试将Blocking Objects
设置为Two D
(同时将Box Collider 2D
添加到ScrollView
和Panel
)和Blocking Mask
设置为Ignore Raycast
(以及其他一些事情)无济于事。这些属性的值是否可以组合使用?
本着今天的精神:
你有没有试过用以下方法包装Raycast:
if (!EventSystem.current.IsPointerOverGameObject(touch.fingerId)) {...}
https://answers.unity.com/questions/1406243/ui-in-arcore-helloar-example.html
这是我在StackOverflow上的第一个答案,所以请耐心等待。我正在构建一个类似的应用程序,您可以从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。现在,当您想要将模型扩展到现实世界时,您可以从面板中选择模型并将'place_model'bool设置为true。这很简单,因为您只需要为按钮设置事件监听器,单击按钮时将bool设置为true。下次触摸跟踪的平面时,模型会得到增强。
希望这能解决你的问题......