前言:
记录(四)是用Vuforia做的,现在来探索一下平面检测,仅记录我的学习过程,如果对你有帮助就更好了!
项目构思:
AR家具摆放是AR技术应用比较广泛的领域,而平面检测时实现家具摆放的重要功能,本案例将通过简单的AR家具Demo来展示ARfoundation的平面检测功能。
项目设计:
(1)可以通过对UI的选择实现对家具的选择
(2)可以通过按下确定按钮,固定家具的位置,按下取消按钮删除要摆放的家具
(3)在检测到平面时,可以控制模型的摆放
项目实施:
新建项目,命名为AR_Furniture分别导入ARFoundation和ARCore XR Plugin,进行Android平台的基本设置(在ARFoundation的基本环境配置已经介绍过了)
在Hierarachy窗口的空白处单击鼠标右键,在弹出的菜单中选择XR>AR Session Origin和XR>AR Session。然后我们需要可跟踪对象管理器ARPlaneManager和可跟踪对象ARPlane用来检测与管理平面。在Hierarachy窗口选择AR Session Origin对象,为其添加ARPlaneManager组件,如图所示。
补充一下,ARPlaneManager组件在检测到平面时会实例一个预制体来表示该平面,如果图中的ARPlanePrefab属性没有赋值,ARPlaneManager将会实例一个空对象,并在空对象上挂载ARPlane组件。
这里我们用UI中的Toggle来进行家具的选择,在Hierarachy窗口的空白处单击鼠标右键,在弹出的菜单中选择Create>UI>Toggle,如图所示,两个Toggle分别表示桌子和椅子,分别重命名为DeskToggle和ChairToggle,并修改“Toggle”层级下的“label”的Text属性分别为Desk和Chair,并调整大小和位置。
在“Canvas”的层级下,新建一个“Create Empty”空物体并改名为“Group”。在空物体的属性面板中,通过“Add Component”添加一个名为“Toggle Group”的组件,勾选Allow Switch Off,即允许都不勾选的状态,如图所示。
把两个Toggle拖拽到Canvas的层级下,选中两个“Toggle”,在其“Toggle(Script)”组件中的“Group”中,选择新建的空物体“Group”,如图所示。
现在两个“Toggle”最多只能有一个保持is On的状态,这样就实现了家具二选一的功能。后期还可以实现多选一的功能。
在Hierarachy窗口的空白处单击鼠标右键,在弹出的菜单中选择Create>UI>Button,创建两个按钮来控制模型的放置和删除,分别命名为SureButton和DelButton,如图所示,并修改“Button”层级下的“Text”为对应的文本“确认”和“取消”,调整大小和位置。
开始制作家具预制体,在文末素材链接中,将素材包AR_Furniture.unitypackage导入项目,将Prefabs中的素材Desk和Chair拖入Hierarachy窗口中。选择这两个游戏对象,为其添加碰撞体。通过“Add Component”添加一个名为“Box Collider”的组件,按下“Edit Collider”可以进行碰撞体大小的调整,如图所示。
补充一下,我们进行AR家具的摆放,是利用射线与场景中的物体进行碰撞检测,添加了碰撞体,后期可以通过射线来选择场景中的家具并进行操作。
新建一个C#脚本命名为PlayerRotate,用于控制家具的旋转,代码如下。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerRotate : MonoBehaviour {
float xSpeed = 150.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButton(0))
{
if (Input.touchCount == 1)
{
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * -xSpeed * Time.deltaTime, Space.World);
}
}
}
}
}
为两个家具游戏对象挂载该脚本,如图所示,再拖入Project窗口的Prefabs文件夹中,这样家具的预制体就制作完成了。
新建一个C#脚本命名为AppControler,用于控制家具的摆放,代码如下。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.UI;
[RequireComponent(typeof(ARRaycastManager))]
public class AppControler : MonoBehaviour
{
public Toggle[] toggles;
//存储模型的数组
public GameObject[] spawnPrefabs;
public GameObject[] buttons;
static List<ARRaycastHit> Hits;
private ARRaycastManager mRaycastManager;
//当前要放置的模型
private GameObject spawnedObject = null;
//选择的当前模型的下标
private int currentIndex;
//判断是否选择了家具
private bool ischoose;
private void Start()
{
Hits = new List<ARRaycastHit>();// ARRaycastHit类保存的是发生碰撞时检测到的碰撞体相关信息
mRaycastManager = GetComponent<ARRaycastManager>();
}
//当Toggle被选中时,判断选择哪个模型
public void juadge()
{
bool isOn = false;
foreach (var item in toggles)
{
if (item.isOn)
{
isOn = true;
}
}
if (!isOn) return;
if (toggles[0].isOn)
{
ischoose = true;
currentIndex = 0;
Debug.Log("true");
}
else {
ischoose = true;
currentIndex = 1;
Debug.Log("true");
}
}
void Update()
{
if (Input.touchCount == 0)
return;
var touch = Input.GetTouch(0);
//当检测到平面并且Toggle被选择
if (mRaycastManager.Raycast(touch.position, Hits, TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds)&&ischoose)
{
var hitPose = Hits[0].pose;
if (spawnedObject == null)
{
spawnedObject = Instantiate(spawnPrefabs[currentIndex], hitPose.position, hitPose.rotation);
Changestate();
}
else
{
spawnedObject.transform.position = hitPose.position;
}
}
}
// 当确定按钮被按下
public void OnSureClick() {
//禁用控制模型旋转的脚本
spawnedObject.GetComponent<PlayerRotate>().enabled = false;
Changestate();
spawnedObject = null;
}
//当取消按钮被按下时,按钮消失,删除放置的模型
public void OnDelClick()
{
if (spawnedObject != null) {
Changestate();
DestroyImmediate(spawnedObject);
spawnedObject = null;
}
}
//控制UI按钮的显示
private void Changestate() {
foreach (var item in buttons) {
item.SetActive(!item.activeInHierarchy);
}
}
}
随后把脚本挂载到场景中的AR Session Origin上,并为Toggles、Spawn Prefabs、Buttons赋值,如图所示,注意Toggles和Spawn Prefabs中按钮和模型要一一对应。
选择场景中的DelButton然后单击On Click()下面的“+”号按钮,指定AR Session Origin作
为消息接收对象,选择AppControler的OnDelClick ()函数作为响应按钮单击事件
的回调函数,如图所示。
选择场景中的SureButton然后单击On Click()下面的“+”号按钮,指定AR Session Origin作为消息接收对象,选择AppControler的OnSureClick() 函数作为响应按钮单击事件的回调函数,如图所示。
选择场景中的两个Toggle,然后单击On Value Changed(Boolean)下面的“+”号按钮,指定AR Session Origin作为消息接收对象,选择AppControler的juadge() 函数作为响应按钮单击事件,如图所示
存在问题
这里因为在点击UI时,还是会认为可能在放置家具。
因此我们可以先update中判断是否按下了按钮,在lateupdate中决定是否要摆放家具(还没有做)
同时用toggle来做选项有点low了,后面有时间把它改成图片。
4.项目测试:
打包成apk发布到手机运行
效果如下:
素材链接:
https://pan.baidu.com/s/1M_gyT1vUkY9qh5bLUjNGpg?pwd=2yar
提取码:2yar
源码链接:
https://pan.baidu.com/s/1B-HXQmSbkmVk6FVTA138Dw?pwd=9utd
提取码:9utd
安装包链接:
链接:https://pan.baidu.com/s/1yKa-u-L8RygJ6r0jUUNBMQ?pwd=1234
提取码:1234