您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
153 行
5.9 KiB
153 行
5.9 KiB
using System;
|
|
using Unity.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.XR.ARFoundation;
|
|
using UnityEngine.XR.ARSubsystems;
|
|
|
|
#if UNITY_IOS
|
|
using System.Runtime.InteropServices;
|
|
using UnityEngine.XR.ARKit;
|
|
|
|
// This custom ConfigurationChooser tells the ARKit XR Plugin to use an ARGeoTrackingConfiguration
|
|
// See https://developer.apple.com/documentation/arkit/argeotrackingconfiguration?language=objc
|
|
class ARGeoAnchorConfigurationChooser : ConfigurationChooser
|
|
{
|
|
static readonly ConfigurationChooser s_DefaultChooser = new DefaultConfigurationChooser();
|
|
|
|
static readonly ConfigurationDescriptor s_ARGeoConfigurationDescriptor = new ConfigurationDescriptor(
|
|
// On iOS, the "identifier" used by the ConfigurationDescriptor is the Objective-C metaclass for the type
|
|
// of configuration that should be used. In general, you should not create new ConfigurationDescriptors
|
|
// (you should pick one of the descriptors passed into ChooseConfiguration); however, this will do for this
|
|
// specific case.
|
|
ARGeoTrackingConfigurationClass,
|
|
|
|
// These are the "features" supported by the ARGeoTrackingConfiguration
|
|
Feature.WorldFacingCamera |
|
|
Feature.PositionAndRotation |
|
|
Feature.ImageTracking |
|
|
Feature.PlaneTracking |
|
|
Feature.ObjectTracking |
|
|
Feature.EnvironmentProbes,
|
|
|
|
// Rank is meant to be used as a tie breaker in our implementation of ChooseConfiguration, but since we will
|
|
// always choose this descriptor, it doesn't matter what value we use here.
|
|
0);
|
|
|
|
public override Configuration ChooseConfiguration(NativeSlice<ConfigurationDescriptor> descriptors, Feature requestedFeatures)
|
|
{
|
|
// If location services are running, then we can request an ARGeoTrackingConfiguration by its class pointer
|
|
return Input.location.status == LocationServiceStatus.Running
|
|
? new Configuration(s_ARGeoConfigurationDescriptor, requestedFeatures.Intersection(s_ARGeoConfigurationDescriptor.capabilities))
|
|
: s_DefaultChooser.ChooseConfiguration(descriptors, requestedFeatures);
|
|
}
|
|
|
|
public static extern IntPtr ARGeoTrackingConfigurationClass
|
|
{
|
|
[DllImport("__Internal", EntryPoint = "ARGeoTrackingConfiguration_class")]
|
|
get;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
[RequireComponent(typeof(ARSession))]
|
|
public class EnableGeoAnchors : MonoBehaviour
|
|
{
|
|
#if UNITY_IOS// && !UNITY_EDITOR
|
|
|
|
// See https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.0/manual/extensions.html
|
|
public struct NativePtrData
|
|
{
|
|
public int version;
|
|
public IntPtr sessionPtr;
|
|
}
|
|
|
|
// See https://developer.apple.com/documentation/corelocation/cllocationcoordinate2d?language=objc
|
|
public struct CLLocationCoordinate2D
|
|
{
|
|
public double latitude;
|
|
public double longitude;
|
|
}
|
|
|
|
// ARGeoAnchors requires location services
|
|
void Start() => Input.location.Start();
|
|
|
|
void OnGUI()
|
|
{
|
|
GUI.skin.label.fontSize = 50;
|
|
GUILayout.Space(100);
|
|
|
|
if (ARGeoAnchorConfigurationChooser.ARGeoTrackingConfigurationClass == IntPtr.Zero)
|
|
{
|
|
GUILayout.Label("ARGeoTrackingConfiguration is not supported on this device.");
|
|
return;
|
|
}
|
|
|
|
switch (Input.location.status)
|
|
{
|
|
case LocationServiceStatus.Initializing:
|
|
GUILayout.Label("Waiting for location services...");
|
|
break;
|
|
case LocationServiceStatus.Stopped:
|
|
GUILayout.Label("Location services stopped. Unable to use geo anchors.");
|
|
break;
|
|
case LocationServiceStatus.Failed:
|
|
GUILayout.Label("Location services failed. Unable to use geo anchors.");
|
|
break;
|
|
case LocationServiceStatus.Running:
|
|
GUILayout.Label("Tap screen to add a geo anchor.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
// Can't do anything interesting until location services are running.
|
|
if (Input.location.status != LocationServiceStatus.Running)
|
|
return;
|
|
|
|
if (GetComponent<ARSession>().subsystem is ARKitSessionSubsystem subsystem)
|
|
{
|
|
if (!(subsystem.configurationChooser is ARGeoAnchorConfigurationChooser))
|
|
{
|
|
// Replace the config chooser with our own
|
|
subsystem.configurationChooser = new ARGeoAnchorConfigurationChooser();
|
|
}
|
|
|
|
// We don't have to do this, but it will silence a warning message in Xcode
|
|
// since the ARGeoTrackingConfiguration can only use the GravityAndHeading value.
|
|
subsystem.requestedWorldAlignment = ARWorldAlignment.GravityAndHeading;
|
|
|
|
// Make sure we have a native ptr
|
|
if (subsystem.nativePtr == IntPtr.Zero)
|
|
return;
|
|
|
|
// Get the session ptr from the native ptr data
|
|
var session = Marshal.PtrToStructure<NativePtrData>(subsystem.nativePtr).sessionPtr;
|
|
if (session == IntPtr.Zero)
|
|
return;
|
|
|
|
var screenTapped = Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended;
|
|
if (screenTapped)
|
|
{
|
|
// Get last known location data
|
|
var locationData = Input.location.lastData;
|
|
|
|
// Add a geo anchor. See GeoAnchorsNativeInterop.m to see how this works.
|
|
AddGeoAnchor(session, new CLLocationCoordinate2D
|
|
{
|
|
latitude = locationData.latitude,
|
|
longitude = locationData.longitude
|
|
}, locationData.altitude);
|
|
}
|
|
|
|
DoSomethingWithSession(session);
|
|
}
|
|
}
|
|
|
|
[DllImport("__Internal")]
|
|
static extern void DoSomethingWithSession(IntPtr session);
|
|
|
|
[DllImport("__Internal", EntryPoint = "ARSession_addGeoAnchor")]
|
|
static extern void AddGeoAnchor(IntPtr session, CLLocationCoordinate2D coordinate, double altitude);
|
|
#endif
|
|
}
|