Skip to content

Instantly share code, notes, and snippets.

@rubit0
Created November 1, 2021 09:49
Show Gist options
  • Save rubit0/3d267e394751a12b58c0ed8f70d0ac23 to your computer and use it in GitHub Desktop.
Save rubit0/3d267e394751a12b58c0ed8f70d0ac23 to your computer and use it in GitHub Desktop.
MRTK style grab interactable for Unity's XRTK
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.AR;
[RequireComponent(typeof(ARSelectionInteractable))]
public class ARGrabInteractable : ARBaseGestureInteractable
{
private const float PositionSpeed = 12f;
private const float DiffThreshold = 0.0001f;
private Vector3 _targetLocalPosition;
private Transform _instanceTransform;
private bool _isActive;
private float distanceToScreen;
protected override void Awake()
{
base.Awake();
_instanceTransform = transform;
}
/// <inheritdoc />
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
base.ProcessInteractable(updatePhase);
if (_isActive &&
updatePhase == XRInteractionUpdateOrder.UpdatePhase.Dynamic)
{
UpdatePosition();
}
}
/// <inheritdoc />
protected override bool CanStartManipulationForGesture(DragGesture gesture)
{
// If the gesture isn't targeting this item, don't start manipulating.
return gesture.targetObject != null && gesture.targetObject == gameObject;
}
/// <inheritdoc />
protected override void OnStartManipulation(DragGesture gesture)
{
distanceToScreen = arSessionOrigin.camera.WorldToScreenPoint(_instanceTransform.position).z;
}
/// <inheritdoc />
protected override void OnContinueManipulation(DragGesture gesture)
{
_isActive = true;
var screenPosition = new Vector3(gesture.position.x, gesture.position.y, distanceToScreen);
_targetLocalPosition = arSessionOrigin.camera.ScreenToWorldPoint(screenPosition);
}
/// <inheritdoc />
protected override void OnEndManipulation(DragGesture gesture)
{
_isActive = false;
}
private void UpdatePosition()
{
var oldLocalPosition = _instanceTransform.position;
var newLocalPosition = Vector3.Lerp(
oldLocalPosition, _targetLocalPosition, Time.deltaTime * PositionSpeed);
var diffLength = (_targetLocalPosition - newLocalPosition).magnitude;
if (diffLength < DiffThreshold)
{
newLocalPosition = _targetLocalPosition;
_isActive = false;
}
_instanceTransform.position = newLocalPosition;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment