如何在 ARCore 生成的平面上沿摄像机视图方向移动 object/prefab
How to move object/prefab in the direction of camera view on a plane generated by ARCore
我正在使用 LeanTouch+ 平移对象,但它只能根据 android 屏幕在 Y 轴上移动,因此在相机上对象只能上下移动。我想要实现的是能够将物体移动得更远或更靠近相机视图。在 ARCore 中,您首先检测环境,然后将其生成为平面,这就是我需要对象移动到的平面。
此外,如果可能的话,我想在 "detected plane" 上使用 Clamp 来限制比检测到的平面更远的移动
这是我使用 LeanFingerTap 生成 obj 的代码
public void Spawn(LeanFinger finger)
{
if (AndyPlanePrefab != null && finger != null)
{
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
TrackableHitFlags.FeaturePointWithSurfaceNormal;
if (Frame.Raycast(finger.ScreenPosition.x, finger.ScreenPosition.y, raycastFilter, out hit))
{
if(currentNumberofPrefab<numberOfPrefabsAllowed)
{
currentNumberofPrefab = currentNumberofPrefab + 1;
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
// Choose the Andy model for the Trackable that got hit.
if (hit.Trackable is FeaturePoint)
{
AndyPrefab = AndyPointPrefab;
}
else
{
getValue = ItemScrollList.valuePrefab;
if (getValue == 1)
{
AndyPrefab = AndyPlanePrefab[0];
Debug.Log("value 1");
}
else if (getValue == 2)
{
AndyPrefab = AndyPlanePrefab[1];
Debug.Log("value 2");
}
else if (getValue == 3)
{
AndyPrefab = AndyPlanePrefab[2];
Debug.Log("value 3");
}
else if (getValue == 4)
{
AndyPrefab = AndyPlanePrefab[3];
Debug.Log("value 4");
}
else if (getValue == 5)
{
AndyPrefab = AndyPlanePrefab[4];
Debug.Log("value 5");
}
}
// Instantiate Andy model at the hit pose.
var andyObject = Instantiate(AndyPrefab, hit.Pose.position, hit.Pose.rotation);
//adding tag to andyObject for destroying spawn purposes
andyObject.tag = "HomePrefab";
// Compensate for the hitPose rotation facing away from the raycast (i.e. camera).
andyObject.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
// Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
// world evolves.
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
// Make Andy model a child of the anchor.
andyObject.transform.parent = anchor.transform;
}
}
}
}
}
您可以通过在 (0, 0, 0)
.
中创建一个预制件来实现这一点,该预制件具有一个空游戏对象作为父对象,您的对象作为子对象
然后,当您检测到飞机时,您可以使用 Session.GetTrackable
将飞机添加到列表中。
然后你可以使用这段代码在检测到的平面的中心实例化你的预制件:
Anchor anchor = m_AllPlanes[0].CreateAnchor(m_AllPlanes[0].CenterPose);
var obj = Instantiate(myPrefab, m_AllPlanes[0].CenterPose);
obj.transform.parent = anchor.transform;
如果你想让它离相机更远或更近,你可以在局部z移动obj。然后你的夹子可以是 m_AllPlanes[0].CenterPose.position.z - m_AllPlanes[0].ExtentZ
到 m_AllPlanes[0].CenterPose.position.z + m_AllPlanes[0].ExtentZ
我建议使用游戏对象创建预制件的原因是为了能够使用本地坐标,因为 ARCore 坐标在每个会话中都会发生变化。
我正在使用 LeanTouch+ 平移对象,但它只能根据 android 屏幕在 Y 轴上移动,因此在相机上对象只能上下移动。我想要实现的是能够将物体移动得更远或更靠近相机视图。在 ARCore 中,您首先检测环境,然后将其生成为平面,这就是我需要对象移动到的平面。
此外,如果可能的话,我想在 "detected plane" 上使用 Clamp 来限制比检测到的平面更远的移动
这是我使用 LeanFingerTap 生成 obj 的代码
public void Spawn(LeanFinger finger)
{
if (AndyPlanePrefab != null && finger != null)
{
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
TrackableHitFlags.FeaturePointWithSurfaceNormal;
if (Frame.Raycast(finger.ScreenPosition.x, finger.ScreenPosition.y, raycastFilter, out hit))
{
if(currentNumberofPrefab<numberOfPrefabsAllowed)
{
currentNumberofPrefab = currentNumberofPrefab + 1;
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
// Choose the Andy model for the Trackable that got hit.
if (hit.Trackable is FeaturePoint)
{
AndyPrefab = AndyPointPrefab;
}
else
{
getValue = ItemScrollList.valuePrefab;
if (getValue == 1)
{
AndyPrefab = AndyPlanePrefab[0];
Debug.Log("value 1");
}
else if (getValue == 2)
{
AndyPrefab = AndyPlanePrefab[1];
Debug.Log("value 2");
}
else if (getValue == 3)
{
AndyPrefab = AndyPlanePrefab[2];
Debug.Log("value 3");
}
else if (getValue == 4)
{
AndyPrefab = AndyPlanePrefab[3];
Debug.Log("value 4");
}
else if (getValue == 5)
{
AndyPrefab = AndyPlanePrefab[4];
Debug.Log("value 5");
}
}
// Instantiate Andy model at the hit pose.
var andyObject = Instantiate(AndyPrefab, hit.Pose.position, hit.Pose.rotation);
//adding tag to andyObject for destroying spawn purposes
andyObject.tag = "HomePrefab";
// Compensate for the hitPose rotation facing away from the raycast (i.e. camera).
andyObject.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
// Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
// world evolves.
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
// Make Andy model a child of the anchor.
andyObject.transform.parent = anchor.transform;
}
}
}
}
}
您可以通过在 (0, 0, 0)
.
然后,当您检测到飞机时,您可以使用 Session.GetTrackable
将飞机添加到列表中。
然后你可以使用这段代码在检测到的平面的中心实例化你的预制件:
Anchor anchor = m_AllPlanes[0].CreateAnchor(m_AllPlanes[0].CenterPose);
var obj = Instantiate(myPrefab, m_AllPlanes[0].CenterPose);
obj.transform.parent = anchor.transform;
如果你想让它离相机更远或更近,你可以在局部z移动obj。然后你的夹子可以是 m_AllPlanes[0].CenterPose.position.z - m_AllPlanes[0].ExtentZ
到 m_AllPlanes[0].CenterPose.position.z + m_AllPlanes[0].ExtentZ
我建议使用游戏对象创建预制件的原因是为了能够使用本地坐标,因为 ARCore 坐标在每个会话中都会发生变化。