参照官方实例
ObjectManipulationController.cs
namespace GoogleARCore.Examples.ObjectManipulation
{
using System.Collections.Generic;
using GoogleARCore;
using UnityEngine;
#if UNITY_EDITOR
// Set up touch input propagation while using Instant Preview in the editor.
using Input = InstantPreviewInput;
#endif
public class ObjectManipulationController : MonoBehaviour
{
private bool _isQuitting = false;
public void Update()
{
UpdateApplicationLifecycle();
}
public void Awake()
{
// Enable ARCore to target 60fps camera capture frame rate on supported devices.
// Note, Application.targetFrameRate is ignored when QualitySettings.vSyncCount != 0.
Application.targetFrameRate = 60;
}
private void UpdateApplicationLifecycle()
{
// Exit the app when the 'back' button is pressed.
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
// Only allow the screen to sleep when not tracking.
if (Session.Status != SessionStatus.Tracking)
{
Screen.sleepTimeout = SleepTimeout.SystemSetting;
}
else
{
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
if (_isQuitting)
{
return;
}
if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
{
ShowAndroidToastMessage("Camera permission is needed to run this application.");
_isQuitting = true;
Invoke("DoQuit", 0.5f);
}
else if (Session.Status.IsError())
{
ShowAndroidToastMessage(
"ARCore encountered a problem connecting. Please start the app again.");
_isQuitting = true;
Invoke("DoQuit", 0.5f);
}
}
private void DoQuit()
{
Application.Quit();
}
private void ShowAndroidToastMessage(string message)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity =
unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (unityActivity != null)
{
AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
AndroidJavaObject toastObject =
toastClass.CallStatic<AndroidJavaObject>(
"makeText", unityActivity, message, 0);
toastObject.Call("show");
}));
}
}
}
}
ManipulationSystem.cs
namespace GoogleARCore.Examples.ObjectManipulation
{
using UnityEngine;
public class ManipulationSystem : MonoBehaviour
{
private static ManipulationSystem _instance = null;
private DragGestureRecognizer _dragGestureRecognizer = new DragGestureRecognizer();
private PinchGestureRecognizer _pinchGestureRecognizer = new PinchGestureRecognizer();
private TwoFingerDragGestureRecognizer _twoFingerDragGestureRecognizer =
new TwoFingerDragGestureRecognizer();
private TapGestureRecognizer _tapGestureRecognizer = new TapGestureRecognizer();
private TwistGestureRecognizer _twistGestureRecognizer = new TwistGestureRecognizer();
public static ManipulationSystem Instance
{
get
{
if (_instance == null)
{
var manipulationSystems = FindObjectsOfType<ManipulationSystem>();
if (manipulationSystems.Length > 0)
{
_instance = manipulationSystems[0];
}
else
{
Debug.LogError("No instance of ManipulationSystem exists in the scene.");
}
}
return _instance;
}
}
/// <summary>
/// Gets the Drag gesture recognizer.
/// </summary>
public DragGestureRecognizer DragGestureRecognizer
{
get
{
return _dragGestureRecognizer;
}
}
public PinchGestureRecognizer PinchGestureRecognizer
{
get
{
return _pinchGestureRecognizer;
}
}
public TwoFingerDragGestureRecognizer TwoFingerDragGestureRecognizer
{
get
{
return _twoFingerDragGestureRecognizer;
}
}
public TapGestureRecognizer TapGestureRecognizer
{
get
{
return _tapGestureRecognizer;
}
}
public TwistGestureRecognizer TwistGestureRecognizer
{
get
{
return _twistGestureRecognizer;
}
}
public GameObject SelectedObject { get; private set; }
public void Awake()
{
if (Instance != this)
{
Debug.LogWarning("Multiple instances of ManipulationSystem detected in the scene." +
" Only one instance can exist at a time. The duplicate instances" +
" will be destroyed.");
DestroyImmediate(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
}
public void Update()
{
DragGestureRecognizer.Update();
PinchGestureRecognizer.Update();
TwoFingerDragGestureRecognizer.Update();
TapGestureRecognizer.Update();
TwistGestureRecognizer.Update();
}
internal void Deselect()
{
SelectedObject = null;
}
internal void Select(GameObject target)
{
if (SelectedObject == target)
{
return;
}
Deselect();
SelectedObject = target;
}
}
}
PawnManipulator.cs
namespace GoogleARCore.Examples.ObjectManipulation
{
using GoogleARCore;
using UnityEngine;
public class PawnManipulator : Manipulator
{
public Camera FirstPersonCamera;
public GameObject PawnPrefab;
public GameObject ManipulatorPrefab;
protected override bool CanStartManipulationForGesture(TapGesture gesture)
{
if (gesture.TargetObject == null)
{
return true;
}
return false;
}
protected override void OnEndManipulation(TapGesture gesture)
{
if (gesture.WasCancelled)
{
return;
}
if (gesture.TargetObject != null)
{
return;
}
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon;
if (Frame.Raycast(
gesture.StartPosition.x, gesture.StartPosition.y, raycastFilter, out hit))
{
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
var gameObject = Instantiate(PawnPrefab, hit.Pose.position, hit.Pose.rotation);
var manipulator =
Instantiate(ManipulatorPrefab, hit.Pose.position, hit.Pose.rotation);
gameObject.transform.parent = manipulator.transform;
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
manipulator.transform.parent = anchor.transform;
manipulator.GetComponent<Manipulator>().Select();
}
}
}
}
}
DetectedPlaneGenerator.cs
namespace GoogleARCore.Examples.Common
{
using System.Collections.Generic;
using GoogleARCore;
using UnityEngine;
public class DetectedPlaneGenerator : MonoBehaviour
{
public GameObject DetectedPlanePrefab;
private List<DetectedPlane> _newPlanes = new List<DetectedPlane>();
public void Update()
{
// Check that motion tracking is tracking.
if (Session.Status != SessionStatus.Tracking)
{
return;
}
Session.GetTrackables<DetectedPlane>(_newPlanes, TrackableQueryFilter.New);
for (int i = 0; i < _newPlanes.Count; i++)
{
GameObject planeObject =
Instantiate(DetectedPlanePrefab, Vector3.zero, Quaternion.identity, transform);
planeObject.GetComponent<DetectedPlaneVisualizer>().Initialize(_newPlanes[i]);
}
}
}
}