Search Unity

GestureRecognizer.OnHoldStarted Delay

Discussion in 'AR/VR (XR) Discussion' started by kwcae, Sep 10, 2018.

  1. kwcae

    kwcae

    Joined:
    May 26, 2017
    Posts:
    34
    When using unity's built in gesture recognizer (UnityEngine.XR.WSA.Input.GestureRecognizer) on the HoloLens we're encountering a strange delay in the triggering of the gesture depending on what is begin grabbed.

    When pinching while looking at a simple-ish UI panel, our gesture is captured and the drag method is triggered almost instantaneously. When pinching over a mesh, the grab gesture must be held for nearly 3 seconds before the system recognizes it.

    General FPS during interactions remains well above 60fps, the UI panel has a box collider attached, the mesh, a simplified mesh collider.

    Does anyone have any insight into what's happening here and why? simplified interaction manager class below.

    Update:
    After adding several debug calls it appears that UI panels are getting OnPointerDown events from somewhere well before OnGrabStart is triggered, with OnGrabStart sometimes not even being called yet them still being drag-able. Meshes withteh same dragable code on them only respond to OnGrabStart triggering them.

    Code:
    Code (CSharp):
    1. public class HoloInteractionManager : MonoBehaviour {
    2.     //Truncated for example
    3.  
    4.     private void ToggleGestureRecognizer(bool start = true) {
    5.         if(gr == null) {
    6.             gr = new GestureRecognizer();
    7.             gr.SetRecognizableGestures(GestureSettings.Tap | GestureSettings.Hold);
    8.         }
    9.  
    10.         if(start && !gr.IsCapturingGestures()) {
    11.             ListenForTapGesture();
    12.             ListenForGrabGesture();
    13.             gr.StartCapturingGestures();
    14.         } else if(start == false && gr.IsCapturingGestures()) {
    15.             gr.StopCapturingGestures();
    16.             ListenForTapGesture(false);
    17.             ListenForGrabGesture(false);
    18.         }
    19.     }
    20.  
    21.     public void ListenForGrabGesture(bool start = true) {
    22.         if(start) {
    23.             gr.HoldStarted += OnGrabStart;
    24.             gr.HoldCompleted += OnGrabStop;
    25.         } else {
    26.             gr.HoldStarted -= OnGrabStart;
    27.             gr.HoldCompleted -= OnGrabStop;
    28.         }
    29.     }
    30.  
    31.     private void OnGrabStart(HoldStartedEventArgs args) {
    32.         cursor.ChangeCursor(CursorType.Grab);
    33.      
    34.         grabbedObject.SendMessageUpwards("OnPointerDown", new PointerEventData(EventSystem.current), SendMessageOptions.DontRequireReceiver);
    35.     }
    36.  
    37.     private void OnGrabStop(HoldStartedEventArgs args) {
    38.         cursor.ChangeCursor(CursorType.Pointer);
    39.  
    40.         grabbedObject.SendMessageUpwards("OnPointerUp", new PointerEventData(EventSystem.current), SendMessageOptions.DontRequireReceiver);
    41.     }
    42.  
    43.     private Vector3 inputSourcePos = Vector3.zero;
    44.     private void InitializeInputSources() {
    45.         InteractionManager.InteractionSourceDetected += InteractionSourceDetected;
    46.         InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
    47.         InteractionManager.InteractionSourceLost += InteractionSourceLost;
    48.     }
    49.  
    50.     private void InteractionSourceDetected(InteractionSourceDetectedEventArgs args) {
    51.         if(args.state.source.kind == InteractionSourceKind.Hand){
    52.             //Change cursor as hand is detected
    53.             cursor.ChangeCursor(CursorType.Ring);
    54.  
    55.             if(!args.state.sourcePose.TryGetPosition(out inputSourcePos)) {
    56.                 //@TODO: Unable to get data, do something if needed?
    57.             }
    58.         } else {
    59.             Debug.LogWarning("Interaction Source '" + args.state.source.kind + "' is not supported at this time.");
    60.         }
    61.     }
    62.  
    63.     private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs args) {
    64.         if(args.state.source.kind == InteractionSourceKind.Hand){
    65.             if(!args.state.sourcePose.TryGetPosition(out inputSourcePos)) {
    66.                 //@TODO: Unable to get data, do something
    67.                 Debug.LogError("Unable to get input source position.");
    68.             }
    69.         }
    70.     }
    71.  
    72.     private void InteractionSourceLost(InteractionSourceLostEventArgs args){
    73.         if(args.state.source.kind == InteractionSourceKind.Hand) {
    74.             if(grabbedObject != null) {
    75.                 OnGrabStop(new HoldCompletedEventArgs());
    76.             } else {
    77.                 cursor.ChangeCursor(CursorType.Pointer);
    78.             }
    79.         } else {
    80.             //Debug.LogWarning("Interaction Source '" + args.state.source.kind + "' is not supported at this time.");
    81.         }
    82.  
    83.         inputSourcePos = Vector3.zero;
    84.     }
    85. }
    86.  
    87. public class Hologram : Placeable, IPointerDownHandler, IPointerUpHandler {
    88.     //Truncated for example
    89.  
    90.     protected override void Awake() {
    91.         base.Awake();
    92.         hologramType = HologramType.UI;
    93.     }
    94.  
    95.     public void OnPointerDown(PointerEventData eventData){
    96.         //Debug.Log("OnPointerDown for: " + gameObject.name + " triggered");
    97.         StartDragging();
    98.     }
    99.  
    100.         public void OnPointerUp(PointerEventData eventData) {
    101.         //Debug.Log("OnPointerUp for: " + gameObject.name + " triggered");
    102.         StopDragging();
    103.     }
    104. }
    105.  
    106. public abstract class Placeable : MonoBehaviour{
    107.     //Truncated for example
    108.  
    109.     public void StartDragging(){
    110.         if(isPlaceable) {
    111.             isDragging = true;
    112.             InvokeRepeating("DragTransformUpdate", 0f, 0.02f); //0.02f to drag at reduced update resembling 50fps
    113.         }
    114.     }
    115.  
    116.     public void StopDragging() {
    117.         if(isDragging) {
    118.             isDragging = false;
    119.             CancelInvoke("DragTransformUpdate");
    120.             inputPreviousPos = Vector3.zero;
    121.         }
    122.     }
    123.  
    124.     protected Vector3 inputPreviousPos = Vector3.zero;
    125.     private float perFrameLimit = 0.015f;
    126.     private void DragTransformUpdate(){
    127.         if(inputPreviousPos != Vector3.zero){
    128.             //Limit the maximum per frame movement amount to avoid accidentally throwing something far, far away when lowering one's hand
    129.             Vector3 clampedDelta = appMgr.intMgr.GetInputSourcePosition() - inputPreviousPos;
    130.             clampedDelta.x = Mathf.Clamp(clampedDelta.x, -perFrameLimit, perFrameLimit);
    131.             clampedDelta.y = Mathf.Clamp(clampedDelta.y, -perFrameLimit, perFrameLimit);
    132.             clampedDelta.z = Mathf.Clamp(clampedDelta.z, -perFrameLimit, perFrameLimit);
    133.  
    134.             //Use clamped input position delta and drag speed modifier to update position,
    135.             gameObject.transform.position += clampedDelta * dragSpeedMultiplier;
    136.         }
    137.         inputPreviousPos = appMgr.intMgr.GetInputSourcePosition();
    138.     }
    139. }
    140.    
     
    Last edited: Sep 10, 2018