Skip to main content
graphwiz.ai
← Back to Posts

Unity XR Development: Setting Up for Meta Quest and Vision Pro

XRUnity
unityxrmeta-questvision-provrar

Unity XR Development: Setting Up for Meta Quest and Apple Vision Pro

Unity is the most popular engine for XR development. This guide covers setting up projects for both Meta Quest and Apple Vision Pro.

Project Setup

Requirements

  • Unity 2022.3 LTS or 2023.2+
  • XR Plugin Management package
  • XR Interaction Toolkit
  • Platform-specific SDKs

Create XR Project

  1. Open Unity Hub → New Project
  2. Select "3D (URP)" template
  3. Name your project

Install XR Packages

Window → Package Manager → Unity Registry

Install:
- XR Plugin Management
- XR Interaction Toolkit
- OpenXR Plugin
- XR Hands

Meta Quest Setup

XR Plugin Configuration

Edit → Project Settings → XR Plug-in Management

✓ Oculus
✓ OpenXR (optional, for cross-platform)

Quest Features

Edit → Project Settings → XR Plug-in Management → Oculus

✓ Shared Depth Buffer
✓ Low Overhead Mode (optional)
✓ Hand Tracking Support
✓ Passthrough Support

Build Settings

File → Build Settings

Platform: Android
Texture Compression: ASTC
Graphics APIs: OpenGLES3 + Vulkan

Android Manifest

Add to Assets/Plugins/Android/AndroidManifest.xml:

<uses-feature android:name="android.hardware.vr.headtracking" />
<uses-permission android:name="com.oculus.permission.HAND_TRACKING" />

Apple Vision Pro Setup

Requirements

  • Unity 2023.2.4f1+
  • Xcode 15.2+
  • visionOS SDK

XR Plugin Configuration

Edit → Project Settings → XR Plug-in Management

✓ Apple visionOS

Build Settings

File → Build Settings

Platform: iOS (visionOS)
Architecture: ARM64

Required Capabilities

In Xcode project settings:

  • ARKit capability
  • Hand Tracking capability

XR Interaction Toolkit

Basic Setup

using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class XRSetup : MonoBehaviour
{
    void Start()
    {
        var xrOrigin = FindObjectOfType<XROrigin>();
        var locomotion = xrOrigin.GetComponent<ActionBasedContinuousMoveProvider>();
    }
}

Grab Interactable

using UnityEngine.XR.Interaction.Toolkit;

public class GrabbableItem : XRGrabInteractable
{
    protected override void OnSelectEntered(SelectEnterEventArgs args)
    {
        base.OnSelectEntered(args);
        // Object grabbed
    }

    protected override void OnSelectExited(SelectExitEventArgs args)
    {
        base.OnSelectExited(args);
        // Object released
    }
}

Hand Tracking

Enable Hand Tracking

using UnityEngine.XR.Hands;

public class HandTrackingExample : MonoBehaviour
{
    XRHandSubsystem handSubsystem;

    void Start()
    {
        var manager = XRGeneralSettings.Instance?.Manager?.activeLoader?.GetLoadedSubsystem<XRHandSubsystem>();
        handSubsystem = manager;
    }

    void Update()
    {
        if (handSubsystem != null)
        {
            handSubsystem.TryUpdateHands(XRHandSubsystem.UpdateType.Dynamic);

            var leftHand = handSubsystem.leftHand;
            var thumbTip = leftHand.GetJoint(XRHandJointID.ThumbTip);

            if (thumbTip.TryGetPose(out var pose))
            {
                transform.position = pose.position;
            }
        }
    }
}

Gesture Detection

public class PinchDetector : MonoBehaviour
{
    public float pinchThreshold = 0.02f;

    public bool IsPinching(XRHand hand)
    {
        var thumbTip = hand.GetJoint(XRHandJointID.ThumbTip);
        var indexTip = hand.GetJoint(XRHandJointID.IndexTip);

        if (thumbTip.TryGetPose(out var thumbPose) &&
            indexTip.TryGetPose(out var indexPose))
        {
            float distance = Vector3.Distance(thumbPose.position, indexPose.position);
            return distance < pinchThreshold;
        }
        return false;
    }
}

Passthrough (Meta Quest)

Enable Passthrough

using UnityEngine.XR.Management;
using UnityEngine.XR;

public class PassthroughController : MonoBehaviour
{
    OVRPassthrough passthrough;
    OVRManager ovrManager;

    void Start()
    {
        ovrManager = FindObjectOfType<OVRManager>();
        passthrough = gameObject.AddComponent<OVRPassthrough>();
        passthrough.Enable();
    }

    public void SetPassthroughEnabled(bool enabled)
    {
        if (enabled)
            passthrough.Enable();
        else
            passthrough.Disable();
    }
}

Room Setup (Vision Pro)

using UnityEngine.XR.ARKit;

public class RoomSetupController : MonoBehaviour
{
    ARKitSessionSubsystem arKitSession;

    void Start()
    {
        arKitSession = XRGeneralSettings.Instance?.Manager?.activeLoader?.GetLoadedSubsystem<ARKitSessionSubsystem>();
    }

    void RequestRoomMapping()
    {
        if (arKitSession != null)
        {
            arKitSession.RequestRoomMapping();
        }
    }
}

Build and Deploy

Meta Quest

# Build APK
File → Build Settings → Build

# Deploy via ADB
adb install -r build.apk

# Or use Oculus Developer Hub

Apple Vision Pro

# Build for device
File → Build Settings → Build And Run

# Or build Xcode project
File → Build Settings → Build (creates .xcodeproj)
# Open in Xcode → Select visionOS target → Deploy

Conclusion

Unity XR development requires platform-specific setup but shares common interaction patterns. Start with XR Interaction Toolkit, add platform-specific features as needed.