目录
📢 本章的目标
完成项目的基础配置,便于我们以后开发。
- 配置SDK
- 显示点云
- 显示检测到的平面
- 完成资源控制脚本
🟥通用配置
1️⃣ 导入ARFoundation SDK
Windows--Packages,选择Advanced:Show preview packages
接着安装ARFoundation、ARCoreXRPlugin、ARKitXRPlugin 。
ARFoundation等默认是当前验证过的版本(verified)。我们选择See all versions,选择3.1.0,Install。
2️⃣ 对场景进行配置
🚩 添加生命周期预制体
层级面板删掉原始摄像机,右键 XR,添加AR Session Origin、AR Session。
这两个组件包含了摄像机、ARFoundation的生命周期等等功能。我们之后会经常调用这两个物体中组件的功能。
🚩 实现检测显示点云
a、ARSessionOrigin 物体添加 ARPointCloudManager 组件
该组件功能就是实现检测并显示点云。但点云什么样?那就需要我们b步骤进行配置。
b、层级面板右键XR-AR Default Point Cloud,将该物体制成点云预制体,删掉层级面板的该物体。将该预制体赋值给ARPointCloudManager 组件
🚩 实现检测显示平面
a、ARSessionOrigin 物体添加 ARPlaneManager 组件
同理,平面什么样?就需要b步骤进行配置。
b、层级面板右键XR-AR Default Plane,将该物体制成平面预制体,删掉层级面板的该物体。将该预制体赋值给ARPlaneManager 组件
DetectionMode:控制检测显示水平平面,竖直平面、都检测,还是都不检测。
🚩 添加控制点云、平面的脚本
上面我们做的是实现了设备检测到真实环境中特征点、平面时,显示点云和平面。
那我们也需要控制这些检测到的点云、平面,让他们隐藏或者显示等。
所以我们写一个脚本,这个脚本 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
}
🟧 ARFoundation4.x独特配置
随着ARFoundation的迭代,在4.x版本后,ARFoundation就成为了UnityXR的子功能。
要使用ARFoundation需勾选如下选项。(若你也导入了ARCore,同样勾选ARCore)
大家还有什么问题,欢迎在下方留言!
如果你有 技术的问题 或 项目开发
都可以加下方联系方式
和我聊一聊你的故事🧡