LoginSignup
1

posted at

updated at

【Unity(C#)】ARFoundationにおける平面検知シーケンスの実装

はじめに

GIFのような処理を実装することが多く、再参照コストがもったいないのでメモします。
PlaneDetection.gif

バージョン情報

諸々名前 バージョン
Unity 2020.3.4f1
ARFoundation 4.1.7
ARCore XR Plugin 4.1.7
ARKit XR Plugin 4.1.7
XR Plugin Management 4.0.1

コード

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class PlaneDetectionDemo : MonoBehaviour
{
    [SerializeField] private GameObject arObject;
    [SerializeField] private GameObject scanGuide;
    [SerializeField] private GameObject detectGuide;
    [SerializeField] private ARRaycastManager arRaycastManager;
    [SerializeField] private ARPlaneManager arPlaneManager;

    private readonly List<ARRaycastHit> hits = new List<ARRaycastHit>();
    private bool isDeteced;
    private Vector2 screenCenter;

    private void Start()
    {
        screenCenter = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
    }

    private void Update()
    {
        if (isDeteced)
        {
            return;
        }

        var isHit = arRaycastManager.Raycast(screenCenter, hits, TrackableType.PlaneWithinPolygon);
        if (isHit)
        {
            //RayとARPlaneが衝突したところのPose
            var hitPose = hits[0].pose;
            detectGuide.transform.SetPositionAndRotation(hitPose.position, hitPose.rotation);
            detectGuide.SetActive(true);
            scanGuide.SetActive(false);
        }
        else
        {
            detectGuide.SetActive(false);
            scanGuide.SetActive(true);
        }
        
        if (Input.touchCount > 0)
        {
            var touch = Input.GetTouch(0);

            if (touch.phase == TouchPhase.Began)
            {
                if (isHit)
                {
                    //RayとARPlaneが衝突したところのPose
                    var hitPose = hits[0].pose; 
                    //オブジェクトの配置
                    arObject.transform.position = hitPose.position;
                    arObject.SetActive(true);
                    var cameraPos = Camera.main.transform.position;
                    cameraPos.y = arObject.transform.position.y;
                    arObject.transform.LookAt(cameraPos);

                    //平面認識の機能をオフ
                    arPlaneManager.requestedDetectionMode = PlaneDetectionMode.None;
                    foreach (ARPlane plane in arPlaneManager.trackables)
                    {
                        plane.gameObject.SetActive(false);
                    }

                    detectGuide.SetActive(false);
                    scanGuide.SetActive(false);
                    isDeteced = true;
                }
            }
        }
    }
}

処理の流れとして、まずはスキャンを促すUIを表示します。
次に画面の中央からRayを出し、検出した平面と衝突した場合は画面タップを促すUIを表示します。
タップしたら画面の中央から出したRayと平面との交点にオブジェクトを表示するという流れです。

オブジェクトの青い部分はそのオブジェクトの正面方向となっており、
体験者に正対するようにしています。

スキャンを促すUIについては、ARFoundationのデモに含まれているのでお借りしました。

【参考リンク】:Unity-Technologies/arfoundation-demos

参考リンク

【Unity(C#)】ARFoundationで認識した平面をオンオフ、平面認識機能そのものをオンオフする方法

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1