ARFoundation丨(二)基础配置

提示:选中右侧目录,可快速找到所需内容

本系列博客地址:传送门

本节目的:完成项目的基础配置,便于我们以后开发。

一、SDK环境配置

安装必备的SDK。

a、Windows--Packages:

Advanced:Show preview packages

 

b、安装ARFoundation、ARCoreXRPlugin、ARKitXRPlugin 。

ARFoundation等默认是当前验证过的版本(verified)。上述包我们统一选择See all versions,选择3.1.0,Install。

二、 场景配置

1、生命周期组件

层级面板删掉原始摄像机,右键 XR,添加AR Session OriginAR Session

这两个组件包含了摄像机、ARFoundation的生命周期等等功能。我们之后会经常掉这两个物体中组件的功能。

2、实现检测显示点云

a、ARSessionOrigin 物体添加 ARPointCloudManager 组件

该组件功能就是实现检测并显示点云。但点云什么样?那就需要我们b步骤进行配置。

b、层级面板右键XR-AR Default Point Cloud,将该物体制成点云预制体,删掉层级面板的该物体。将该预制体赋值给ARPointCloudManager 组件

3、实现检测显示平面

a、ARSessionOrigin 物体添加 ARPlaneManager 组件

同理,平面什么样?就需要b步骤进行配置。

b、层级面板右键XR-AR Default Plane,将该物体制成平面预制体,删掉层级面板的该物体。将该预制体赋值给ARPlaneManager 组件

 DetectionMode:控制检测显示水平平面,竖直平面、都检测,还是都不检测。

4、资源控制

上面我们做的是实现了设备检测到真实环境中特征点、平面时,显示点云和平面。

那我们也需要控制这些检测到的点云、平面,让他们隐藏或者显示等。

所以我们写一个脚本,这个脚本 Public 中提供了公开方法,方便我们对这些物体进行控制

这个脚本随意挂在哪都行。脚本功能如下:

  • 提供:启用与禁用平面检测
  • 提供:显示与隐藏检测到的平面
  • 得到:当前AR会话是否正在运行,并被跟踪(即该设备当前能否确定其在世界上的位置和方向)
  • 自动运行:检查设备运行环境,能否支持ARFoundation
  • 自动运行:包含一种省电策略,当设备没找到识别目标,允许屏幕在最后激活一段时间后变暗
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

public class Skode_ARFManager : MonoBehaviour
{
    #region Public Parameters

    public static Skode_ARFManager ins;

    #endregion


    #region Private Parameters

    ARPlaneManager m_ARPlaneManager;

    /// <summary>
    /// 当前识别出的平面
    /// </summary>
    List<ARPlane> detectPlanes = new List<ARPlane>();

    /// <summary>
    /// 当前是否要显示平面
    /// </summary>
    bool isShowPlane = true;

    #endregion


    #region MonoBehaviour CallBacks

    private void Awake()
    {
        ins = this;

        m_ARPlaneManager = FindObjectOfType<ARPlaneManager>();
    }

    void Start()
    {
        CheckDevice();

        m_ARPlaneManager.planesChanged += OnPlaneChanged;
    }

    private void Update()
    {
        SaveElePolicy();
    }

    void OnDisable()
    {
        m_ARPlaneManager.planesChanged -= OnPlaneChanged;
    }

    #endregion


    #region Public Methods

    // 启用与禁用平面检测
    // 程序默认启用,启用时一直不停地检测平面。关闭时则不会再检测新平面了。
    public void Skode_PlaneDetectionContro(bool value)
    {
        m_ARPlaneManager.enabled = value;
        if (m_ARPlaneManager.enabled)
        {
            print("已启用平面检测");
        }
        else
        {
            print("已禁用平面检测");
        }
    }

    // 显示与隐藏检测到的平面
    public void Skode_PlaneContro(bool value)
    {
        isShowPlane = value;

        for (int i = detectPlanes.Count - 1; i >= 0; i--)
        {
            if (detectPlanes[i] == null || detectPlanes[i].gameObject == null)
                detectPlanes.Remove(detectPlanes[i]);
            else
                detectPlanes[i].gameObject.SetActive(value);
        }
    }

    /// <summary>
    /// 得到当前AR会话是否正在运行,并被跟踪(即,该设备能够确定其在世界上的位置和方向)。
    /// </summary>
    public bool Skode_IsTracking()
    {
        bool isTracking = false;

        if (ARSession.state == ARSessionState.SessionTracking)
        {
            isTracking = true;
        }

        return isTracking;
    }

    #endregion


    #region Private Methods

    //在ARFoundation新发现平面时,将平面添加进列表里,便于我们控制这些平面
    void OnPlaneChanged(ARPlanesChangedEventArgs arg)
    {
        for (int i = 0; i < arg.added.Count; i++)
        {
            detectPlanes.Add(arg.added[i]);
            arg.added[i].gameObject.SetActive(isShowPlane);
        }
    }

    //检查设备运行环境
    void CheckDevice()
    {
        if (ARSession.state == ARSessionState.NeedsInstall)
        {
            ShowAndroidToastMessage("AR is supported, but requires an additional install. .");
            Invoke("Quit", 1);
        }
        else if (ARSession.state == ARSessionState.Ready)
        {
            Debug.Log("AR is supported and ready.");
        }
        else if (ARSession.state == ARSessionState.Unsupported)
        {
            ShowAndroidToastMessage("AR is not supported on the current device.");
            Invoke("Quit", 1);
        }
    }

    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");
            }));
        }
    }

    void Quit()
    {
        Application.Quit();
    }

    /// <summary>
    /// 一种省电设置,当设备没找到识别目标,允许屏幕在最后激活一段时间后变暗
    /// </summary>
    void SaveElePolicy()
    {
        if (ARSession.state != ARSessionState.SessionTracking)
        {
            const int lostTrackingSleepTimeout = 15;
            Screen.sleepTimeout = lostTrackingSleepTimeout;
        }
        else
        {
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
        }
    }

    #endregion
}

本节结束,下节我们讲放置物体

Enjoy~

发布了329 篇原创文章 · 获赞 85 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/weixin_38239050/article/details/105094215