Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

[NEW UPDATE!] Fingers - Touch Gestures - #1 in Quality, Support and Features : Dozens of Gestures✓

Discussion in 'Assets and Asset Store' started by jjxtra, Apr 25, 2016.

  1. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Of course, I will do it today and send the update.
     
  2. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Will this work? It has the full gesture info for the previous gesture. Should be a little more than just the previous touch positions...
    Code (csharp):
    1.  
    2.  
    3.         [Tooltip("Whether to process Unity touch events. If false, you will need to implement the VirtualTouch* methods to implement touch handling.")]
    4.         public bool ProcessUnityTouches = true;
    5.  
    6. ...
    7.  
    8.         if (ProcessUnityTouches)
    9.         {
    10.             ProcessTouches();
    11.         }
    12.         ProcessVirtualTouches();
    13.         if (ProcessUnityTouches)
    14.         {
    15.             ProcessMouseButtons();
    16.             ProcessMouseWheel();
    17.         }
    18.  
    19. ...
    20.  
    21.         /// <summary>
    22.         /// Previous touch locations
    23.         /// </summary>
    24.         public System.Collections.ObjectModel.ReadOnlyCollection<GestureTouch> PreviousTouches { get { return previousTouches.AsReadOnly(); } }
    25.  
     
    Last edited: Feb 18, 2019
  3. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    That was fast, 2.6.1 is now on the store with the new ProcessUnityTouches and PreviousTouches property.
     
  4. Falondrian

    Falondrian

    Joined:
    Dec 4, 2018
    Posts:
    33
    Thanks a lot, that was really fast :) One issue though: AFAIK reimplementing "GestureTouchFromTouch" requires "previousTouchPositions", not "previousTouches". The latter contains similar data, however, it is readonly and "GestureTouchFromTouch" also writes to previousTouchPositions. Maybe you could pass "previousTouchPositions" as a parameter to "VirtualTouchObjectHandler"?
     
  5. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Would this work?

    Code (csharp):
    1.  
    2.         /// <summary>
    3.         /// Create a gesture touch object from a virtual touch object and updates the previous position internally
    4.         /// </summary>
    5.         /// <param name="touchId">Virtual touch/finger id</param>
    6.         /// <param name="touchPosition">Virtual touch position</param>
    7.         /// <param name="touchPrevPosition">Virtual touch position</param>
    8.         /// <param name="touchPhase">Virtual touch phase</param>
    9.         /// <param name="touchPressure">Virtual touch pressure</param>
    10.         /// <returns>GestureTouch</returns>
    11.         public GestureTouch GestureTouchFromVirtualTouch(int touchId, Vector2 touchPosition, UnityEngine.TouchPhase touchPhase, float touchPressure = 0.0f)
    12.  
     
  6. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    I sent an update again, redownload 2.6.1
     
  7. Falondrian

    Falondrian

    Joined:
    Dec 4, 2018
    Posts:
    33
    Perfect! Transformed my code into a 2-liner. Thanks for the super fast support!
     
  8. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    You are welcome. If you have a moment to spare to write a review if you haven't already it is always appreciated. Please post a link to your game when it is ready to buy, I would love to try it out.
     
  9. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    Hi there. So I've gotten both tap and doubleTap gestures working, but not scale or rotate.

    To set the scene, I'm using AR to place a plane on the world then I want to be able to fine tune its placement using gestures to position, scale, and rotate the plane. Do you know if anyone else is using your system to do that atm?

    Right now, rotate, pan, and scale are all being caught as double taps. Are the two types of gesture mutually exclusive? I don't see any examples in of both existing in your demo...

    Cheers,

    J^2
     
    Last edited: Mar 1, 2019
  10. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Many people are using Fingers Gestures for AR and VR. You need to create a scale and rotate gesture. Then hook into the state updated and rotate or scale the plane based on the gestures. Does that make sense? Is there something I am not understanding right?
     
  11. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    I have done all that. For some reason, both the scale and rotate gestures aren't being caught. No matter what I do, if I use two fingers, it reports as a double tap. Is there something additional I need to do to catch the scale/rotate gesture, perhaps I have to handle those before checking for a double tap? Here's what I have implented so far:

    In start() I have:


    CreateTapGesture();
    CreateDoubleTapGesture();
    CreateScaleGesture();
    CreateRotateGesture();
    CreatePanGesture();


    And then as my implementations:


    private void Pan_Updated(GestureRecognizer gesture)
    {
    if (gesture.CurrentTrackedTouches.Count != 0 && !IsGameScanning && IsGridPlaced)
    {
    GestureTouch t = gesture.CurrentTrackedTouches[0];
    Log("Pan gesture, state: {0}, position: {1},{2} -> {3},{4}", gesture.State, t.PreviousX, t.PreviousY, t.X, t.Y);

    }
    }

    private void CreatePanGesture()
    {
    panGesture = new PanGestureRecognizer();
    panGesture.StateUpdated += Pan_Updated;
    panGesture.MaximumNumberOfTouchesToTrack = 2;
    FingersScript.Instance.AddGesture(panGesture);
    }

    private void RotateGestureCallback(GestureRecognizer gesture)
    {
    if (gesture.State == GestureRecognizerState.Executing && !IsGameScanning && IsGridPlaced)
    {
    minesweeperObject.transform.Rotate(0.0f, 0.0f, rotateGesture.RotationRadiansDelta * Mathf.Rad2Deg);
    }
    }

    private void CreateRotateGesture()
    {
    rotateGesture = new RotateGestureRecognizer();
    rotateGesture.MaximumNumberOfTouchesToTrack = 1;
    rotateGesture.StateUpdated += RotateGestureCallback;
    FingersScript.Instance.AddGesture(rotateGesture);
    }

    private void Scale_Updated(GestureRecognizer gesture)
    {
    Log("Scale: {0},{1}", gesture.State, (gesture as ScaleGestureRecognizer).ScaleMultiplier);
    if (gesture.State == GestureRecognizerState.Executing && IsGridPlaced)
    {
    float scale = (gesture as ScaleGestureRecognizer).ScaleMultiplier;

    if (scale >= 0.999f && scale <= 1.001f)
    {
    return;
    }

    // make Vector3 for scale
    Vector3 newScale = minesweeperObject.transform.localScale * scale;

    // don't mess with z scale
    newScale.z = 1.0f;

    // zoom and move towards the scaling position
    minesweeperObject.transform.localScale = newScale;
    }

    }

    private void CreateScaleGesture()
    {
    scaleGesture = new ScaleGestureRecognizer();
    scaleGesture.MaximumNumberOfTouchesToTrack = 2;
    scaleGesture.StateUpdated += Scale_Updated;
    FingersScript.Instance.AddGesture(scaleGesture);
    }

    private void TapGesture_StateUpdated(GestureRecognizer gesture)
    {
    if (gesture.State == GestureRecognizerState.Ended && IsGameScanning && !IsGridPlaced)
    {
    planeManager.enabled = false;
    cloudManager.enabled = false;

    if (cloudManager.pointCloud != null)
    {
    cloudManager.pointCloud.gameObject.SetActive(false);
    }

    IsGameRunning = false;
    IsGameScanning = false;

    UI.SetUIState(UIManagerAR.UIState.adjusting);

    Vector2 touchPosition = new Vector2(gesture.FocusX, gesture.FocusY);
    if (sessionOrigin != null && sessionOrigin.Raycast(touchPosition, hits, TrackableType.PlaneWithinPolygon))
    {
    Pose hitPose = hits[0].pose;

    referencePoint = referencePointManager.TryAddReferencePoint(hitPose);
    }

    arCameraRay = arCamera.ScreenPointToRay(touchPosition);

    if (Physics.Raycast(arCameraRay, out hitInfo))
    {
    if (hitInfo.collider.gameObject.tag == "ARPlane")
    {
    float x = hitInfo.collider.gameObject.transform.localScale.x * (10f / (float)UI.GetSettings().Width);
    float z = hitInfo.collider.gameObject.transform.localScale.z * (10f / (float)UI.GetSettings().Height);

    if (x < z)
    minesweeperObject.transform.localScale = Vector3.one * x;
    else
    minesweeperObject.transform.localScale = Vector3.one * z;

    minesweeperObject.transform.position = hitInfo.collider.gameObject.transform.position;
    minesweeperObject.transform.rotation = hitInfo.collider.gameObject.transform.rotation;

    UI.UpdateGameStateText("Grid placed! Scale and pan gestures to adjust,\nthen double tap to start", new Color(0f, 1f, 0f, 1f));
    IsGridPlaced = true;
    IsGameScanning = false;
    }
    }
    //Debug.LogFormat("Single tap at {0},{1}", gesture.FocusX, gesture.FocusY);
    }
    }

    private void CreateTapGesture()
    {
    tapGesture = new TapGestureRecognizer();
    tapGesture.StateUpdated += TapGesture_StateUpdated;
    tapGesture.MaximumNumberOfTouchesToTrack = 10;
    FingersScript.Instance.AddGesture(tapGesture);
    }

    private void DoubleTapGestureCallback(GestureRecognizer gesture)
    {
    Debug.LogFormat("Double tap at {0},{1}", gesture.FocusX, gesture.FocusY);
    if (gesture.State == GestureRecognizerState.Ended && IsGridPlaced)
    {
    UI.UpdateGameStateText("Starting game", new Color(0f, 1f, 0f, 1f));
    StartNewGame(UI.GetSettings());
    }
    }

    private void CreateDoubleTapGesture()
    {
    doubleTapGesture = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
    doubleTapGesture.StateUpdated += DoubleTapGestureCallback;
    FingersScript.Instance.AddGesture(doubleTapGesture);
    }


    If you see anything obvious as a flaw, please point it out. Cheers,

    J^2
     
    Last edited: Mar 2, 2019
  12. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Set the double tap to require the tap, scale and rotate to fail?
     
  13. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    OK, so I need to set up a sort of cascade? For example, have the scale require the pan to fail, the rotate to require the scale to fail, and the double tap to require the rotate to fail? Or is there a way to specify all three in a given .RequireGestureRecognizerToFail property?
     
  14. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    I believe the fail property is a list, correct me if I am wrong
     
  15. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    Hmm. In your demo code, I see:


    tapGesture.RequireGestureRecognizerToFail = doubleTapGesture;


    Which is just a straight up assignment. Have you overridden the assignment operator to handle either a single gesture or a list of them?
     
  16. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    AddRequiredGestureRecognizerToFail is the method you want.
     
  17. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    I've added a simple AR / VR plane / object placement demo. I hope it is helpful.

     
  18. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    Awesome! Thanks. I'll tuck into this and let you know how it goes. Cheers!

    J^2
     
  19. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    Well bugger. I'm looking at your example and while it seems straightforward enough, my problem seems to be that the gestures either aren't being initialized properly or I'm perhaps making too many? I've put debug statements as the first line in each gestures callback. What I'm getting back is not making sense. For example, the very first tap I make is reporting:

    Single tap at 0,0
    Single tap at 0,0
    Double tap at 0,0
    Double tap at 0,0


    That's all from one single tap. Yet my app still recognizes the tap and moves into the menu. The next tap, which is on the start game button, also reports:

    Single tap at 0,0
    Single tap at 0,0
    Double tap at 0,0
    Double tap at 0,0


    Again, just one single tap. Very weird right? However, it gets weirder once the AR system starts looking for points. Once it finds a surface and then I tap, it reports:

    Single tap at 1407.42,740.7841
    Double tap at 1407.42,740.7841


    So, it seems to be detecting both a single and double tap at the same time. As I continue to single tap, I get more weird results:

    Single tap at 1407.42,740.7841
    Single tap at 0,0
    Double tap at 1407.42,740.7841
    Double tap at 0,0
    Single tap at 1200.998,638.112
    Double tap at 1200.998,638.112
    Single tap at 1200.998,638.112
    Single tap at 0,0
    Single tap at 1199.894,640.3201
    Double tap at 1199.894,640.3201
    Single tap at 1199.894,640.3201
    Single tap at 0,0
    Double tap at 1199.894,640.3201
    Double tap at 0,0


    To reiterate, these are all single taps. Why I am seeing some taps with 0,0 values and others with proper values is very confusing. Additionally, at the same time I am seeing all these debug outputs for my single and double tap callbacks, I am also getting null value exceptions for the debug outputs of my scale, rotate, and pan gesture callbacks, for example:

    NullReferenceException: A null value was found where an object instance was required.
    at GameManager.Log (System.String text, System.Object[] args) [0x00000] in <filename unknown>:0
    at GameManager.Scale_Updated (DigitalRubyShared.GestureRecognizer gesture) [0x00000] in <filename unknown>:0


    So, I must be doing something wrong, but I'm not able to figure it out just by looking at your example code. From what I can tell, it's all setup the same way. Here's some examples:

    The code for the double tap:

    private void DoubleTapGestureCallback(GestureRecognizer gesture)
    {
    Debug.LogFormat("Double tap at {0},{1}", gesture.FocusX, gesture.FocusY);
    if (gesture.State == GestureRecognizerState.Ended && IsGridPlaced)
    {
    UI.UpdateGameStateText("Starting game", new Color(0f, 1f, 0f, 1f));
    StartNewGame(UI.GetSettings());
    }
    }

    private void CreateDoubleTapGesture()
    {
    doubleTapGesture = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
    doubleTapGesture.StateUpdated += DoubleTapGestureCallback;
    doubleTapGesture.MaximumNumberOfTouchesToTrack = 2;
    FingersScript.Instance.AddGesture(doubleTapGesture);
    }

    And the scale code:

    private void Scale_Updated(GestureRecognizer gesture)
    {
    Log("Scale: {0},{1}", gesture.State, (gesture as ScaleGestureRecognizer).ScaleMultiplier);
    }

    private void CreateScaleGesture()
    {
    scaleGesture = new ScaleGestureRecognizer();
    scaleGesture.MaximumNumberOfTouchesToTrack = 2;
    scaleGesture.StateUpdated += Scale_Updated;
    scaleGesture.AddRequiredGestureRecognizerToFail(rotateGesture);
    scaleGesture.AddRequiredGestureRecognizerToFail(panGesture);
    FingersScript.Instance.AddGesture(scaleGesture);
    }

    So, obviously I must be doing something wrong but I'm just not seeing it. I'm hoping your more experienced eyes might catch what it is I am doing wrong...

    Oh, and in case you were wondering, all the Create methods are being called from GameManager's start() method, so I know they are at least being created as one would expect, otherwise I wouldn't be seeing the debug output, right?

    Any advice or pointers you can provide would be greatly appreciated. Cheers,

    J^2
     
  20. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Double tap should use NumberOfTapsRequired = 2. If you have a single tap gesture, it needs to require the double tap gesture to fail as well.
    Scale gesture already tracks two touches by default I believe.
    Not sure about the null ref, it appears to be in your game manager class.
     
  21. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    OK, well if you look at the code, you will see that the CreateDoubleTapGesture method DOES indeed have NumberOfTapsRequired = 2, so not sure why you are pointing that out specifically. As for the single tap gesture, I do indeed also have the failure requirements met:


    private void CreateTapGesture()
    {
    tapGesture = new TapGestureRecognizer();
    tapGesture.StateUpdated += TapGesture_StateUpdated;
    tapGesture.MaximumNumberOfTouchesToTrack = 1;
    tapGesture.AddRequiredGestureRecognizerToFail(doubleTapGesture);
    tapGesture.AddRequiredGestureRecognizerToFail(scaleGesture);
    tapGesture.AddRequiredGestureRecognizerToFail(rotateGesture);
    tapGesture.AddRequiredGestureRecognizerToFail(panGesture);
    FingersScript.Instance.AddGesture(tapGesture);
    }


    One weird thing I am also noticing. I turned on Show Touches, and single touches are indeed showing up, but when I use two fingers, I don't see the white circles. However, if I touch with two fingers, and then lift one finger, the other finger shows a white circle. So it looks like multi-touch itself isn't working? Is there something global in the project that is just assumed to be set that I perhaps have not?

    And yes, I know the null ref is in my Game Manager script. Please forgive me if I seem brusque, but I do know how to read a log file. I'm not asking you where the null is, I'm asking why? I see nothing in my code that might result in a null ref. And to reiterate, the null refs are happening in ALL the multitouch gestures (rotate, pan, as well as scale). This points to something not getting initialized properly on a global scale. Is there anything in the project that would possibly disable multitouch tracking or is required to get it working properly? Some kind of global project setting?

    J^2
     
  22. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Is Process Unity Touches enabled on your fingers script?
     
  23. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    Certainly is:

    upload_2019-3-7_11-11-39.png
     
  24. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Any chance you can send the project?
     
  25. jjfranzen

    jjfranzen

    Joined:
    Nov 11, 2013
    Posts:
    14
    Let me check with my partner and see if he's OK with giving access.

    J^2
     
  26. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Happy to sign NDA and do a full byte by byte wipe when I'm done looking at it.
     
  27. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
  28. K0ST4S

    K0ST4S

    Joined:
    Feb 2, 2017
    Posts:
    18
    How I set touch area to be image area? I have multiple images. For each image I only want the image I'm touching to be rotated. How do I do that?
    Right now I can use rotate gesture anywhere on the screen and it rotates the first image.
     
    Last edited: Mar 9, 2019
  29. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Set the PlatformSpecificView property of the gesture to the game object the image is on. Make sure enable raycast is on for the image.

    I'd suggest either a rotate gesture for each image, or one rotate gesture where you do a custom ray cast when the gesture begins to see what object it is on top of. If not on top of any object, reset the gesture, in which case do not set the PlatformSpecificView property.
     
    K0ST4S likes this.
  30. halken

    halken

    Joined:
    Mar 11, 2017
    Posts:
    7
    Hi, I'm having trouble with the Pan Gesture. I basically want a clean way to execute some code when the pan starts, and when it ends. I'm doing a Graphics raycast at the beginning to select a target we're going to move during the pan, and when it ends, I set the target to null.

    Currently, I'm using the StateUpdated event, and looking for state Ended to deselect the target. Any other state, if the target is null, it will do the raycast and select a new target. My problem is the cycle of states is not what I'd expect. After the Ended state, I get one more frame of Possible. This causes it to reselect the old target at the end of the pan gesture, just after I released it. For example:

    [click to start pan]
    state: Possible ... for n frames
    state: Executing ... for n frames
    state: Ended (when I release the pan)
    state: Possible (single frame after release)
    [then nothing until I click again to start a new Pan]

    Any ideas?

    I am using Unity 2018.2.13f1, and Fingers 2.5.5 (2018-12-07)
     
  31. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Code (CSharp):
    1.  
    2. // Wrap your selection logic in:
    3. if (gesture.State == GestureRecognizerState.Began)
    4. {
    5. }
    6.  
    7. // Wrap your movement logic in
    8. else if (gesture.State == GestureRecognizerState.Executing)
    9. {
    10. }
    11.  
    12. // Wrap your deselect logic in
    13. else if (gesture.State == GestureRecognizerState.Ended)
    14. {
    15. }
    16.  
    17.  
     
    Last edited: Mar 15, 2019
  32. halken

    halken

    Joined:
    Mar 11, 2017
    Posts:
    7
    Thanks. That solves the problem of unintentional selecting after the Pan ends. But now it is not selecting properly sometimes. Seems like there is a delay on when the Pan begins. And by that time, I have already moved away from the object, and my Raycast fails to select the object. Any way to get the original touch position instead of current?

    Right now, I am using this in Begin state to get the X,Y of the touch:
    gesture.CurrentTrackedTouches[0]

    Otherwise, can I tighten the sensitivity on when a Possible Pan becomes a real Pan and hits Begin state?
     
  33. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    You can set the threshold units on the pan gesture to be 0 if you want instant start. The gesture should have a StartFocusX and StartFocusY as well.
     
  34. halken

    halken

    Joined:
    Mar 11, 2017
    Posts:
    7
    Perfect. Works great.
     
  35. LorenzH

    LorenzH

    Joined:
    Jan 2, 2019
    Posts:
    2
    Hi, I am currently working on a small project where you can Drag&Drap ListItems form a ScrollView into an other ScrollView. How it is described in the readme.txt, gestures are blocked when executed over some UI-Elements like the ScrollView. I added the ListItems and the ScrollView into the PassThrough list but it doesen't seem to work.

    For testing purposes I also added a panel gameObject, outside of the ScrollView, to the passThrough list. Gestures which worked before are now failing (they fail when the gameObject is added to the PassThrough list).

    This is how i added the gameObject to the passThrough list:

    Code (CSharp):
    1.   private void CreateLongPressGesture()
    2.         {
    3.             longPressGestureRecognizer = new LongPressGestureRecognizer();
    4.             longPressGestureRecognizer.PlatformSpecificView = gameObject;
    5.             longPressGestureRecognizer.StateUpdated += LongPressGrestureCallback;
    6.             FingersScript.Instance.AddGesture(longPressGestureRecognizer);
    7.             FingersScript.Instance.PassThroughObjects.Add(gameObject);
    8.         }
    Do you have any ideas how this would work?
     
  36. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    I would get rid of the platform specific view and the pass through view and instead implement a pass through handler. This will let you use code to determine whether the game object can be dragged. Return false to let the gesture execute on the object. In your gesture callback begin state, do a raycast to see where it hit and if it hit something, track it, if not reset the gesture.

    Code (CSharp):
    1. On FingersScript.Instance:
    2.  
    3.         /// <summary>
    4.         /// Optional handler to determine whether a game object will pass through or not.
    5.         /// Null handler gets default gesture capture handling.
    6.         /// Non-null handler that returns null gets default handling.
    7.         /// Non-null handler that returns true captures the gesture.
    8.         /// Non-null handler that returns false passes the gesture through.
    9.         /// </summary>
    10.         public System.Func<GameObject, bool?> CaptureGestureHandler { get; set; }
     
  37. LorenzH

    LorenzH

    Joined:
    Jan 2, 2019
    Posts:
    2
    Hi jjxtra, thanks for the fast response. The PassThroughHandler works great!

    I know it is not part of your framework, but do you know how you can get the UI-Element which was "longPressed"? I tried it with 2dRaycast but I think this only works for gameObject outside of the canvas.

    Code (CSharp):
    1. Vector3 pos = new Vector3(gesture.FocusX, gesture.FocusY, 0.0f);
    2.                 pos = Camera.main.ScreenToWorldPoint(pos);
    3.                 RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.zero);
    4.  
    5.                 if (hit.transform != null && hit.transform.gameObject.name.StartsWith("PassThroughList"))
    6.                 {
    7.                     listComponent = hit.transform.gameObject;
    8.                 }
    You would help me alot. Thanks. =)
     
  38. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    No problem, happy to help, just use EventSystem.current.Raycast
     
  39. Webbstre

    Webbstre

    Joined:
    Mar 7, 2015
    Posts:
    38
    Is there a way to reduce the reaction time from touching and object to beginning to drag? It lasts about a second and I was hoping for it to be near instant.
     
  40. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    If you are using the long press gesture you can reduce the long press time duration via property on the gesture.
     
  41. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    511
    Hi im having trouble implementing something.

    Using the Long Press Component with Maximum 2 touch detection.
    Is it possible to make it so that if there are 2 ongoing touches, the gesture callback GestureRecognizer returns the gesture.FocusX, gesture.FocusY for the LATEST touch to change position in the gesture, instead of the AVERAGE of all touches at every execution?

    In my use case, im using both thumbs to control movement of a turret, and its much more fluid to be able to leave one thumb on the screen while another one starts touching the screen, and then when one thumb leaves the screen, the turret immediately responds to the other thumb that's still on the screen.


    I guess you can think of it as like the joystick, except while one finger is controlling the joystick, another one can override it with its own touch, but if it lets go, the previous finger takes over the joystick again.

    EDIT:
    well after lots of tinkering, the most basic solution that at least works somewhat is
    Code (CSharp):
    1. public void LongPressGestureExecuted(DigitalRubyShared.GestureRecognizer gesture)
    2.     {
    3.         if (gesture.State == GestureRecognizerState.Executing || gesture.State == GestureRecognizerState.Began)
    4.         {      
    5.             if (gesture.CurrentTrackedTouches.Count == 2)
    6.             {        
    7.                 turretPlayer.MoveOnInput(new Vector3(gesture.CurrentTrackedTouches[1].ScreenX, gesture.CurrentTrackedTouches[1].ScreenY, 10f));
    8.             }
    9.             else
    10.             {
    11.                 turretPlayer.MoveOnInput(new Vector3(gesture.CurrentTrackedTouches[0].ScreenX, gesture.CurrentTrackedTouches[0].ScreenY, 10f));
    12.             }
    13.         }      
    14.     }
    Of course this is nowhere near perfect because CurrentTrackedTouches[1] might not be moving at all while CurrentTrackedTouches[0] is the one moving.

    I've seen this method in the GestureRecognizer code:
    Code (CSharp):
    1.  
    2. /// <summary>
    3.         /// Call with the touches that moved
    4.         /// </summary>
    5.         /// <param name="touches">Touches that moved</param>
    6.         public void ProcessTouchesMoved(ICollection<GestureTouch> touches)
    7.  
    But this is a bit beyond my programming level, im not sure if this is what i think it is, and how to connect it with the callback to get just the touches that moved.
    In which case id just pick the second touch if both are moving at the same time.

    EDIT2:
    actually this would probably work:
    Code (CSharp):
    1.  public void LongPressGestureExecuted(DigitalRubyShared.GestureRecognizer gesture)
    2.     {
    3.         if (gesture.State == GestureRecognizerState.Executing || gesture.State == GestureRecognizerState.Began)
    4.         {        
    5.             if (gesture.CurrentTrackedTouches.Count == 2 && gesture.CurrentTrackedTouches[0].TouchPhase != DigitalRubyShared.TouchPhase.Moved)
    6.             {          
    7.                
    8.                 turretPlayer.MoveOnInput(new Vector3(gesture.CurrentTrackedTouches[1].ScreenX, gesture.CurrentTrackedTouches[1].ScreenY, 10f));
    9.             }
    10.             else
    11.             {
    12.                 turretPlayer.MoveOnInput(new Vector3(gesture.CurrentTrackedTouches[0].ScreenX, gesture.CurrentTrackedTouches[0].ScreenY, 10f));
    13.             }
    14.         }        
    15.     }
    but now that im thinking bout it, it might actually be a better game feel to have to Untouch the second thumb before the first thumb works again.

    I got a question, if CurrentTrackedTouches goes from 2 to 1 because CurrentTrackedTouches[0] ended, i assume CurrentTrackedTouches[1] will become CurrentTrackedTouches[0]?
     
    Last edited: Apr 17, 2019
  42. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    It's a little extra tracking but you could store the touch id and vector of each current tracked touch and then compare distances and do appropriate handling. I cannot change FocusX and FocusY as that would break basically everyone.
     
  43. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    511
    yea i figured that's what it'd take.
    Thanks, ill just stick to what i got lol

    one last question,
    i assume Input.multiTouchEnabled = true; is necessary for Fingers to work with multiple touches?
     
  44. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Fingers already sets this in it's script so no need to set it yourself.
     
    luniac likes this.
  45. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
  46. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    How do I go about testing gestures in a scene? I am trying to test my rotation gesture. When I press ALT or CRTL I can see three touches on screen at once, but it's not triggering any rotation code.
     
  47. Romano

    Romano

    Joined:
    Nov 27, 2013
    Posts:
    70
    Hi there, I was wondering if there was an easy way to use swipe gestures simultaneously with image recognition? This is to allow the player to control a character with swipes and also to draw images for special actions. The problem I have is that swipes happen midway through an image being drawn. I thought I would be able to use something like:

    Code (CSharp):
    1. swipeGesture.AddRequiredGestureRecognizerToFail(imageRecognitionScript);
    But it seems that the image recognition script (or at least the one called
    FingersImageGestureHelperComponentScript) isn't a GestureRecognizer in the same way the other scripts are.

    Currently I'm using coroutines to delay the swipe action until after the player has lifted a finger to check if something has been drawn first, but this is introducing a delay and is quite fiddly to work with.

    Would appreciate any help you can give me, thanks! I just bought the asset and I'm loving it so far. Sorry if this turns out to be a noob question...
     
  48. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    511
    if (gesture.State == GestureRecognizerState.Ended)
    {
    Debug.Log(gesture.CurrentTrackedTouches.Count);
    }

    this always returns at least "1", how can i track if there are no touches period?
    i have a simple boolean on my gun object isTouchingScreen, and i wanna set it to false if there are literally no touches on the screen.

    of course id rather not check every frame,
    i use the longpressgesture callback, how do i check inside there?
    public void LongPressGestureExecuted(DigitalRubyShared.GestureRecognizer gesture)


    or is the only way to do it is to check in Update()
    FingersScript.Instance.CurrentTouches.Count


    thanks!

    EDIT:
    its all good i found a different solution.
     
    Last edited: Jun 26, 2019
  49. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    202
    How can I reset the joystick image so that I can move it back to start position if the game is interupted?

    The scenario:
    1. I have OnApplicationPause/Focus logic in my game.
    2. I am moving the joystick.
    3. Game is interrupted by phone call.
    4. I resume game.
    5. Joystick is still in the last position (e.g. to far right). The joystick is stuck in this pivot point even when moved.
    What I have tried:

    • Disable script, enable script.
    • JoystickScript.JoystickExecuted = JoystickExecuted;
      JoystickScript.MoveJoystickToGestureStartLocation = MoveJoystickToGestureStartLocation;

      I assume last attempt is not working as GestureRecognizerState.Executing.
     
  50. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,191
    Please try the demo scenes first to verify that they work, if they do something is not right in you script.
     
unityunity