--- tags: AR Foundation --- # AR Foundation 偵測平面與置放物件 參考影片 {%youtube lelX8GGh_S8 %} Github https://github.com/allinreality/PlaneTracking-ARFoundationUnity3D 1. 開啟3D專案 2. 使用 Package Manager,需要安裝 AR Foundation 套件,看你是使用什麼平台,選擇 ARCore XR Plugin 或 ARKit XR Plugin 套件至少一項 4. 刪除既有場景的攝影機物件 5. 新增物件 XR -> AR Session Origin 6. 新增物件 XR -> AR Session 7. 在 AR Session Origin 中增加以下組件: * AR Plane Manager * AR Point Cloud * AR Point Cloud Manager * AR Raycast Manager * AR Anchor Manager 8. 新增物件 XR -> AR Default Point Cloud,並且做成預置物件,原場景物件刪除,預置物件放到 AR Point Cloud Manager 9. 新增物件 XR -> AR Default Plane,並且做成預置物件,原場景物件刪除,預置物件放到 AR Plane Manager 10. 設計要置放的物件,並且做成預置物件 11. 將 PlaceOnPlane 程式碼匯入專案,並且置放到 AR Session Origin 中 12. 匯入指標圖樣動畫物件「VisualObjectAR.unitypackage」 13. PlaceOnPlane 的 Placed Prefab 欄位放要置放的物件、Visual Object 放置指標圖樣 14. 專案匯出設定為 Android,Player 設定如下: * Graphics API 把 Vulkan 移下或者移除 * Minimun API Level 至少要有 API Level 24 * Scripting Beckend 設定為 IL2CPP 15. Project Setting 的 XR Plug-in Management 設定,選擇 Android 的 ARCore 與 ARKit (iOS) 16. 安裝到手機測試 ## PlaceOnPlane ```csharp= using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; /// <summary> /// Listens for touch events and performs an AR raycast from the screen touch point. /// AR raycasts will only hit detected trackables like feature points and planes. /// /// If a raycast hits a trackable, the <see cref="placedPrefab"/> is instantiated /// and moved to the hit position. /// </summary> [RequireComponent(typeof(ARRaycastManager))] public class PlaceOnPlane : MonoBehaviour { [SerializeField] [Tooltip("Instantiates this prefab on a plane at the touch location.")] GameObject m_PlacedPrefab; UnityEvent placementUpdate; [SerializeField] GameObject visualObject; /// <summary> /// The prefab to instantiate on touch. /// </summary> public GameObject placedPrefab { get { return m_PlacedPrefab; } set { m_PlacedPrefab = value; } } /// <summary> /// The object instantiated as a result of a successful raycast intersection with a plane. /// </summary> public GameObject spawnedObject { get; private set; } void Awake() { m_RaycastManager = GetComponent<ARRaycastManager>(); if (placementUpdate == null) placementUpdate = new UnityEvent(); placementUpdate.AddListener(DiableVisual); } bool TryGetTouchPosition(out Vector2 touchPosition) { if (Input.touchCount > 0) { touchPosition = Input.GetTouch(0).position; return true; } touchPosition = default; return false; } void Update() { if (!TryGetTouchPosition(out Vector2 touchPosition)) return; if (m_RaycastManager.Raycast(touchPosition, s_Hits, TrackableType.PlaneWithinPolygon)) { // Raycast hits are sorted by distance, so the first one // will be the closest hit. var hitPose = s_Hits[0].pose; if (spawnedObject == null) { spawnedObject = Instantiate(m_PlacedPrefab, hitPose.position, hitPose.rotation); } else { //repositioning of the object spawnedObject.transform.position = hitPose.position; } placementUpdate.Invoke(); } } public void DiableVisual() { visualObject.SetActive(false); } static List<ARRaycastHit> s_Hits = new List<ARRaycastHit>(); ARRaycastManager m_RaycastManager; } ```