如何使用Unity在ARKit中隐藏用于平面检测的平面预制件?

时间:2018-07-24 12:16:03

标签: c# unity3d augmented-reality arkit

我正在使用ARKit构建一个用于垂直平面检测的应用程序。一旦检测到平面,我就需要关闭平面检测。即使在检测到平面后,它仍会跟踪并找到更多的平面。检测到。

using System;
using System.Collections.Generic;
using UnityEngine.EventSystems;

namespace UnityEngine.XR.iOS

{
    public class UnityARHitTestExample : MonoBehaviour
    {
        public Transform m_HitTransform;
        public float maxRayDistance = 30.0f;
    public LayerMask collisionLayer = 1 << 10;  //ARKitPlane layer

    public List<GameObject> Instaobj = new List<GameObject>();

    public Transform ForSelect;
    int Select;
    UnityARCameraManager obj=new UnityARCameraManager();
    UnityARGeneratePlane obb=new UnityARGeneratePlane();


    bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
    {
        List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);
        if (hitResults.Count > 0) {
            foreach (var hitResult in hitResults) {
                Debug.Log ("Got hit!");
                obj.Hideplane();
               // obb.planePrefab.SetActive(false);





                m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
                m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
                Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));








                return true;
            }
        }
        return false;
    }

    // Update is called once per frame
    void Update () {


        #if UNITY_EDITOR   //we will only use this script on the editor side, though there is nothing that would prevent it from working on device
        if (Input.GetMouseButtonDown (0)) {
            Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            RaycastHit hit;

            //we'll try to hit one of the plane collider gameobjects that were generated by the plugin
            //effectively similar to calling HitTest with ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent
            if (Physics.Raycast (ray, out hit, maxRayDistance, collisionLayer)) {
                //we're going to get the position from the contact point
                m_HitTransform.position = hit.point;
                Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));

                //and the rotation from the transform of the plane collider
                m_HitTransform.rotation = hit.transform.rotation;
            }
        }
        #else
        if (Input.touchCount > 0 && m_HitTransform != null )
        {
            var touch = Input.GetTouch(0);
            if ((touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved) &&  !EventSystem.current.IsPointerOverGameObject(touch.fingerId))
            {
                var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
                ARPoint point = new ARPoint {
                    x = screenPosition.x,
                    y = screenPosition.y
                };

                // prioritize reults types
                ARHitTestResultType[] resultTypes = {
                    //ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingGeometry,
                    ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent, 
                    // if you want to use infinite planes use this:
                    //ARHitTestResultType.ARHitTestResultTypeExistingPlane,
                    //ARHitTestResultType.ARHitTestResultTypeEstimatedHorizontalPlane, 
                    //ARHitTestResultType.ARHitTestResultTypeEstimatedVerticalPlane, 
                    //ARHitTestResultType.ARHitTestResultTypeFeaturePoint
                }; 

                foreach (ARHitTestResultType resultType in resultTypes)
                {
                    if (HitTestWithResultType (point, resultType))
                    {
                        return;
                    }
                }
            }
        }
        #endif

    }


}

}

下面是UnityARCameraManager

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.iOS;

public class UnityARCameraManager : MonoBehaviour {

    public Camera m_camera;
    private UnityARSessionNativeInterface m_session;
    private Material savedClearMaterial;

    [Header("AR Config Options")]
    public UnityARAlignment startAlignment = UnityARAlignment.UnityARAlignmentGravity;
    public UnityARPlaneDetection planeDetection = UnityARPlaneDetection.Horizontal;
    public ARReferenceImagesSet detectionImages = null;
    public bool getPointCloud = true;
    public bool enableLightEstimation = true;
    public bool enableAutoFocus = true;
    private bool sessionStarted = false;
    private ARKitWorldTrackingSessionConfiguration config;

// Use this for initialization
void Start () {

    m_session = UnityARSessionNativeInterface.GetARSessionNativeInterface();

    Application.targetFrameRate = 60;
    //ARKitWorldTrackingSessionConfiguration config = new ARKitWorldTrackingSessionConfiguration();
     config = new ARKitWorldTrackingSessionConfiguration();
    config.planeDetection = planeDetection;
    config.alignment = startAlignment;
    config.getPointCloudData = getPointCloud;
    config.enableLightEstimation = enableLightEstimation;
    config.enableAutoFocus = enableAutoFocus;
    if (detectionImages != null) {
        config.arResourceGroupName = detectionImages.resourceGroupName;
    }

    if (config.IsSupported) {
        m_session.RunWithConfig (config);
        UnityARSessionNativeInterface.ARFrameUpdatedEvent += FirstFrameUpdate;
    }

    if (m_camera == null) {
        m_camera = Camera.main;
    }
}

void FirstFrameUpdate(UnityARCamera cam)
{
    sessionStarted = true;
    UnityARSessionNativeInterface.ARFrameUpdatedEvent -= FirstFrameUpdate;
}

public void SetCamera(Camera newCamera)
{
    if (m_camera != null) {
        UnityARVideo oldARVideo = m_camera.gameObject.GetComponent<UnityARVideo> ();
        if (oldARVideo != null) {
            savedClearMaterial = oldARVideo.m_ClearMaterial;
            Destroy (oldARVideo);
        }
    }
    SetupNewCamera (newCamera);
}

private void SetupNewCamera(Camera newCamera)
{
    m_camera = newCamera;

    if (m_camera != null) {
        UnityARVideo unityARVideo = m_camera.gameObject.GetComponent<UnityARVideo> ();
        if (unityARVideo != null) {
            savedClearMaterial = unityARVideo.m_ClearMaterial;
            Destroy (unityARVideo);
        }
        unityARVideo = m_camera.gameObject.AddComponent<UnityARVideo> ();
        unityARVideo.m_ClearMaterial = savedClearMaterial;
    }
}

// Update is called once per frame

void Update () {

    if (m_camera != null && sessionStarted)
    {
        // JUST WORKS!
        Matrix4x4 matrix = m_session.GetCameraPose();
        m_camera.transform.localPosition = UnityARMatrixOps.GetPosition(matrix);
        m_camera.transform.localRotation = UnityARMatrixOps.GetRotation (matrix);

        m_camera.projectionMatrix = m_session.GetCameraProjection ();
    }

}


public void Hideplane()
{

    config.planeDetection = UnityARPlaneDetection.None;

}

}

我尝试使用Hideplane()方法,仍然显示蓝色平面 Plane prefab

我在UnityhittestAR示例中进行了尝试。我一直在寻找类似FocusSquare的示例。一旦我们触摸屏幕后检测到飞机,物体就会被放置并且不再进行跟踪

1 个答案:

答案 0 :(得分:0)

它是一个临时解决方案,但可以。在您的UnityARKitScene中添加一个新脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EventHandler : MonoBehaviour {
    public GameObject MainPlane;
    public GameObject DestroyedPlane;
    public GameObject p;
    public int Got;
    private void Start()
    {
        Instantiate(p);
    }
    private void Update()
    {

        MainPlane = GameObject.Find("Plane");
        if(MainPlane!=null){
            if(Got==0){
                MainPlane.name = "MainPlane";
                Got = 1;
            }
            if(Got==1){
                MainPlane = null;
                DestroyedPlane = GameObject.Find("Plane");
                Destroy(DestroyedPlane);
            }
        }
    }
}