ARCore之路-平面检测

  在前一节中,我们创建了一个App Controller,构建了我们的AR应用框架来做应用程序的整体流程处理,但是,如果运行我们前面的框架,什么也不会看到,本节中,我们将使用摄像机生成的点云数据来检测和创建平面,同时我们还要可视化检测出来的平面,帮助用户指出一个可用的平面在哪里。

一、新建一个平面

  前面我们介绍过Prefabs,当检测到真实世界中的平面时,我们需要一种在虚拟空间中表示这一特征的方法,这就是使用可视化的虚拟平面,为了使用代码来创建平面,我们也要制作一个平面的Prefabs,当检测到更多真实世界的平面时,我们还要实例化并附加更多的Prefabs,以使可用的虚拟平面更大。
  在Hierarchy窗口,点击右键,选择 “Create”-> “3D Object” ->”Plane”,新建一个平面,命名为”VisualDetectedPlane”如下图所示:

这里写图片描述

  在这里,我们特别需要关注的是在平面的Inspector窗口中,Position一定要归0,同时还要确保Scale为(1,1,1),如果这里有少许偏移,那么在用代码实例化平面后也同样会出现偏移。

这里写图片描述

二、应用纹理

  有了平面,我们还要给平面赋一个材质,以便在实例化后用户能看到这个平面。保持当前”VisualDetectedPlane”属于被选中状态,点击Mesh Renderer组件左侧的箭头打开Mesh Renderer组件详细信息,在详细信息栏展开后点击Element0后面的那个小圆圈,这将打开材质选择面板,在材质选择面板中,选择”PlaneGrid”,这就为我们的“VisualDetectedPlane”平面赋上了一个漂亮的可视材质纹理了。如下图所示:

这里写图片描述

三、添加平面渲染脚本

  有了平面,也有了材质纹理了,但我们还需要一个渲染器来将检测到或者扩展出来的平面渲染出来,如果我们自己去写这个渲染器将不会是一件愉快的工作,好在ARCore已经为我们写好了,我们只需要将这个写好的类附加到我们的平面上即可,点击 “Add Component”按钮,在搜索框中输入”Detected”,可以找到DetectedPlaneVisualizer,将这个脚本附件到我们的平面上。如下图所示:

这里写图片描述

四、制作平面Prefabs

  与前面所说一样,在Hierarchy窗口中,将VisualDetectedPlane平面拖动到Projects窗口中的Prefabs文件夹中,这样我们就做好了VisualDetectedPlane平面的Prefabs,然后删除Hierarchy窗口VisualDetectedPlane平面。

这里写图片描述

五、更新App Controller

  好了,有了可视化的平面Prefabs了,我们现在需要更新一下我们的App Controller,以便处理检测到的平面的可视化问题。因为平面中我们添加加的DetectedPlaneVisualizer是由ARCore提供的,我们需要在我们的代码中引用其命名空间GoogleARCore.Examples.Common。
  然后我们再申明一个GameObject,注意这个变量是public型的,等挂载这个脚本后,这个变量会出现在Inspector窗口中,另外,我们还实例化了两个list来存放我们新检测到的平面和已检测到的所有平面,代码如下所示:

    public GameObject DetectedPlanePrefab;
    private List<DetectedPlane> mNewPlanes = new List<DetectedPlane>();
    private List<DetectedPlane> mAllPlanes = new List<DetectedPlane>();

  接下来我们在update()方法中添加如下代码:

        Session.GetTrackables<DetectedPlane>(mNewPlanes, TrackableQueryFilter.New);
        for (int i = 0; i < mNewPlanes.Count; i++)
        {
            GameObject planeObject = Instantiate(DetectedPlanePrefab, Vector3.zero, Quaternion.identity,
                transform);
            planeObject.GetComponent<DetectedPlaneVisualizer>().Initialize(mNewPlanes[i]);
        }

        Session.GetTrackables<DetectedPlane>(mAllPlanes);

  这段代码的逻辑如下,首先我们从Session中得到标记为new的DetectedPlane,并将这些检测到的平面赋给mNewPlanes list表,然后我们根据新检测到的mNewPlanes数量,对每一个新检测到的平面实例化一个我们之前制作的VisualDetectedPlane平面,并将新实例化的平面赋给planeObject以便显示和利用。最后我们还保留一份所有检测到的平面的副本。完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleARCore;
using GoogleARCore.Examples.Common;

public class AppController : MonoBehaviour {

    private bool mIsQuitting = false;
    public GameObject DetectedPlanePrefab;
    private List<DetectedPlane> mNewPlanes = new List<DetectedPlane>();
    private List<DetectedPlane> mAllPlanes = new List<DetectedPlane>();
    // Use this for initialization
    void Start () {
        OnCheckDevice();
    }

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

        Session.GetTrackables<DetectedPlane>(mNewPlanes, TrackableQueryFilter.New);
        for (int i = 0; i < mNewPlanes.Count; i++)
        {
            GameObject planeObject = Instantiate(DetectedPlanePrefab, Vector3.zero, Quaternion.identity,
                transform);
            planeObject.GetComponent<DetectedPlaneVisualizer>().Initialize(mNewPlanes[i]);
        }

        Session.GetTrackables<DetectedPlane>(mAllPlanes);

    }
    /// <summary>
    /// 检查设备
    /// </summary>
    private void OnCheckDevice()
    {
        if(Session.Status == SessionStatus.ErrorSessionConfigurationNotSupported)
        {
            ShowAndroidToastMessage("ARCore在本机上不受支持或配置错误!");
            mIsQuitting = true;
            Invoke("DoQuit", 0.5f);
        }
        else if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
        {
            ShowAndroidToastMessage("AR应用的运行需要使用摄像头,现无法获取到摄像头授权信息,请允许使用摄像头!");
            mIsQuitting = true;
            Invoke("DoQuit", 0.5f);
        }
        else if (Session.Status.IsError())
        {
            ShowAndroidToastMessage("ARCore运行时出现错误,请重新启动本程序!");
            mIsQuitting = true;
            Invoke("DoQuit", 0.5f);
        }
    }
    /// <summary>
    /// 管理应用的生命周期
    /// </summary>
    private void UpdateApplicationLifecycle()
    {
        if (Session.Status != SessionStatus.Tracking)
        {
            const int lostTrackingSleepTimeout = 15;
            Screen.sleepTimeout = lostTrackingSleepTimeout;
        }
        else
        {
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
        }

        if (mIsQuitting)
        {
            return;
        }
    }
    /// <summary>
    /// 退出程序
    /// </summary>
    private void DoQuit()
    {
        Application.Quit();
    }
    /// <summary>
    /// 弹出信息提示
    /// </summary>
    /// <param name="message">要弹出的信息</param>
    private void ShowAndroidToastMessage(string message)
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        if (unityActivity != null)
        {
            AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
            unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
            {
                AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,message, 0);
                toastObject.Call("show");
            }));
        }
    }
}

六、测试平面检测功能

  至此,我们已经更新了App Controller,也制作了我们需要可视化的平面,现在我们要把这个脚本挂载到场景中,在Hierarchy窗口中,右键选择”Create Empty”,新建一个空对象,并命名为”AppController”。

这里写图片描述

  在Project窗口中的”Scripts”文件夹中将”AppController.cs”拖到Hierarchy窗口中的”AppController”物体上。或者在”AppController”的 Inspector窗口中,选择”Add Component”,在搜索框中输入”AppController”,将其挂载到该物体上。
这里写图片描述

  点击Detected Plane Prefab后的小圆圈打开物体选择对话框,选择”VisualDetectedPlane”,如下图所示:

这里写图片描述

  功能开发完毕,进行联机测试,按Ctrl+Shift+B打开Build Settings,确保选中我们的场景文件。

这里写图片描述

  点击按钮 “Build And Run”,保存生成的apk应用到我们指定的路径,开始编译我们的工程。

这里写图片描述

这里写图片描述

  等待片刻,编译完后会自动下载安装到我们的手机上,拿着手机前后左右移动一下,我们将会看到我们检测到的平面以可视化的形式展现出来了。

这里写图片描述

<think>我们正在讨论EasyAR与ARCore平面检测方面的集成或实现方法。根据提供的引用,我们知道:-ARFoundation是Unity的跨平台AR框架,支持ARKit和ARCore(引用1)。-EasyAR4.0可以与UnityARFoundation结合使用(引用2)。因此,我们可以通过UnityARFoundation来集成EasyAR和ARCore平面检测功能。###实现步骤1.**环境配置**:-安装Unity(建议使用较新版本,支持ARFoundation)。-UnityPackageManager中安装ARFoundation和ARCoreXRPlugin(针对Android)或ARKitXRPlugin(针对iOS)。-导入EasyARSDK(从EasyAR官网下载)。2.**设置ARSession**:-在场景中创建空对象,添加`ARSession`组件(用于管理AR会话)。-创建`ARSessionOrigin`(用于控制虚拟内容在真实世界中的位置和方向)。3.**平面检测设置**:-在`ARSessionOrigin`对象上添加`ARPlaneManager`组件(用于检测平面)。-配置`ARPlaneManager`:指定平面预制体(用于可视化检测到的平面)和检测参数。4.**集成EasyAR**:-根据EasyAR4Learn教程(引用2),将EasyAR的ARSession与UnityARFoundation的ARSession进行整合。通常,EasyAR提供了一些预制体和组件,我们需要将其与ARFoundation的组件协同工作。-具体来说,可能需要使用EasyAR提供的相机配置或一些扩展功能,但平面检测主要依赖ARFoundation的`ARPlaneManager`。5.**编写代码(可选)**:-如果需要自定义平面检测的行为,可以编写脚本订阅`ARPlaneManager`的事件(如平面添加、更新、删除)。###示例代码以下是一个简单的脚本,用于在检测到新平面时输出信息:```csharpusingUnityEngine;usingUnityEngine.XR.ARFoundation;publicclassPlaneDetectionHandler:MonoBehaviour{privateARPlaneManagerplaneManager;voidStart(){planeManager=GetComponent<ARPlaneManager>();planeManager.planesChanged+=OnPlanesChanged;}voidOnPlanesChanged(ARPlanesChangedEventArgsargs){foreach(varplaneinargs.added){Debug.Log($"平面检测到:{plane.trackableId}");}}}```###注意事项-在Android设备上,确保在PlayerSettings中设置正确的AndroidSDK和NDK路径,并设置最低API级别(ARCore要求Android7.0及以上)。-在iOS设备上,需要设置ARKit的相应配置。-由于EasyAR和ARFoundation的集成,可能需要参考EasyAR的文档来配置一些特定的设置,例如相机权限、初始化等。###引用说明以上步骤参考了ARFoundation的通用使用方法[^1]和EasyAR4Learn教程中关于与ARFoundation集成的部分[^2]。§§相关问题§§1.如何优化平面检测的性能?2.在EasyAR和ARFoundation集成中,如何处理不同平台的差异(如ARCore和ARKit)?3.除了平面检测,EasyAR和ARFoundation还能实现哪些AR功能?</think>### EasyAR与ARCore平面检测集成实现指南 EasyAR与ARCore平面检测方面的集成主要通过Unity的AR Foundation框架实现。以下是具体实现步骤: #### 一、环境配置 1. **安装Unity**(建议2021 LTS或更新版本) 2. **导入必要包**: - AR Foundation(Unity Package Manager中安装) - ARCore XR Plugin(Android平台) - EasyAR Sense SDK(从EasyAR官网下载最新版) 3. **配置Player Settings**: ```markdown - Android: * Minimum API Level: Android 7.0 (API 24) * ARCore Required: Enabled - iOS: * Camera Usage Description: 添加AR功能描述 ``` #### 二、平面检测实现步骤 1. **场景设置**: ```markdown a. 创建空对象 -> 添加`AR Session Origin`组件 b. 添加子对象 -> 挂载`AR Plane Manager`组件 c. 在`AR Plane Manager`中指定平面预制体(可视化平面) ``` 2. **脚本实现核心逻辑**: ```csharp using UnityEngine; using UnityEngine.XR.ARFoundation; public class PlaneDetector : MonoBehaviour { private ARPlaneManager planeManager; void Start() { planeManager = GetComponent<ARPlaneManager>(); planeManager.planesChanged += OnPlanesChanged; } void OnPlanesChanged(ARPlanesChangedEventArgs args) { foreach (var plane in args.added) { Debug.Log($"检测到新平面: {plane.trackableId}"); // 在此添加自定义逻辑(如放置物体) } } } ``` 3. **EasyAR集成增强**: ```markdown - 在`AR Session`对象上添加EasyAR的`ARSession`组件 - 配置EasyAR Key(官网注册获取) - 使用EasyAR的`ImageTarget`组件增强图像识别能力 ``` #### 三、关键参数调优 | 参数 | ARCore默认值 | 优化建议 | |------|-------------|---------| | 检测精度 | 中等 | 调高`ARPlaneManager.detectionThreshold` | | 平面大小 | 0.5m² | 增大`minExtent`减少小平面 | | 更新频率 | 60Hz | 场景静态时可降低至30Hz | #### 四、跨平台处理 ```csharp // 平台特定功能实现 #if UNITY_ANDROID // ARCore专属功能(如深度API) using GoogleARCore; #elif UNITY_IOS // ARKit专属扩展 using UnityEngine.XR.ARKit; #endif ``` 深度API可实现更精确的平面边缘检测[^4] #### 五、测试与验证 1. **真机测试要求**: - Android:支持ARCore的设备列表 - iOS:A9及以上处理器设备 2. **验证方法**: ```markdown - 移动设备扫描不同表面(桌面/地板/墙面) - 检查平面生成位置准确性 - 测试多平面交接处处理 ``` > **注意**:当同时使用EasyAR和ARCore时,优先使用ARCore平面检测功能,EasyAR主要提供图像识别增强[^2]。AR Foundation已抽象化底层差异,ARKit和ARCore平面检测结果会统一处理[^3]。
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_DavidWang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值