Search Unity

Missing touch events - my fault?

Discussion in 'iOS and tvOS' started by dayglo, Jul 10, 2010.

  1. dayglo

    dayglo

    Joined:
    Apr 28, 2010
    Posts:
    24
    Hi guys,

    Does anyone else experience missed touch events on iphone? I've noticed that I didn't miss any a week ago, and the more and more I work on my game, the more seem to be missed. It's more noticeable with the 'began' and 'ended' events, since they're the ones I trigger visible game actions with (crouching and jumping).

    Can touch events be affected by poor performance and bad optimisation of my scripts? Should I be catching the touch events in a tight update loop and putting my 'action' code into co-routines (or something)?

    I'm using unity3 beta3 with the remote, and I'm using this common pattern in an update loop:

    Code (csharp):
    1. for (var touch : Touch in Input.touches) {
    2.  
    3.         if (touch.phase == TouchPhase.Began) {
    4.             ...do some fun stuff
    5.         }
    6.         if (touch.phase == TouchPhase.Stationary) {
    7.             ...do some fun stuff
    8.         }
    9.         if (touch.phase == TouchPhase.Moved) {
    10.             ...do some fun stuff
    11.         }
    12.         if (touch.phase == TouchPhase.Ended ) {
    13.             ...do yet more fun stuff
    14.         }
    15. }
    If no-one else has noticed this sort of thing, I'll re-convert my project back to Unity 1.7 and see if I get the same results...

    Gee
     
  2. SquaxShaun

    SquaxShaun

    Joined:
    Jun 22, 2009
    Posts:
    63
    I've noticed that sometimes the packets arrive out of order via the unity remote in 1.7, seem to be okay on the actual device though.

    I haven't got hold of the beta yet, but if your game's overall framerate has dropped it could be stealing cycles from the touch event handling. Try putting the input handling script in an empty test scene, and see if it is behaving the same.
     
  3. dayglo

    dayglo

    Joined:
    Apr 28, 2010
    Posts:
    24
    Yes, if they came out of order that would definitely explain it.

    I'll try your suggestion - also I heard that b4 is out tomorrow, so I'l be able to test on my device.
     
  4. dayglo

    dayglo

    Joined:
    Apr 28, 2010
    Posts:
    24
    just doing a bit of testing in an empty scene and it is definitely missing phases.

    Submitted a bug report.
     
  5. Lord_Pall

    Lord_Pall

    Joined:
    Sep 25, 2009
    Posts:
    52
    I can confirm missing phases.

    I wonder if it's related to framerate? I seem to get an ended consistently, it's just begin that seems to skip..
     
  6. eltonbird

    eltonbird

    Joined:
    Mar 9, 2010
    Posts:
    41
    I have the same problem here, which is a lot more common on the iPod Touch Gen 1 I'm using to test for worst case performance.

    I don't seem to miss many "begin", but "end" frequently fials to respond and the Input.touchCount is stuck on 1..

    (Unity 3.0 beta 3)
     
  7. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    I have had this problem from day one with Unity. I suspect the issue is because Unity is only letting you look at touches once per frame. On the Apple side of things, touches are pushed as a separate event and are delivered every time through the runloop. It may be possible that multiple Apple touch events get kicked through for a single Unity frame though I am not certain of this, just suspecting.
     
  8. dxchen

    dxchen

    Joined:
    Sep 17, 2009
    Posts:
    4
    I did some test about the missing touch in the Unity iPhone(it really happened), and try to find out another way to avoid that situation.

    here is some parts of my test code you may add some code to compare the iPhoneTouch provided by Unity

    Code (csharp):
    1.  
    2. private var samePosition : int = 0;
    3. function Awake ()
    4. {
    5.     touchInit();
    6. }
    7.  
    8. function Update () {
    9. }
    10.  
    11. function OnGUI() {
    12.     if(Event.current.type != EventType.Layout  Event.current.type != EventType.Repaint)
    13.     {
    14.         touchEvents();
    15.     }
    16.  
    17.     GUI.Label (Rect (10,200,320,40), "eTC=" + eventTouchCount + " tTC=" +totalTouchCount +" L="+myPhoneTouchDeltaLength[0]+" samePosition=" + samePosition);
    18. }
    19.  
    20. private var eventTouchCount : int;
    21. private var totalTouchCount : int;
    22. private var myPhoneTouchFingerId : int[];
    23. private var myPhoneTouchBeganPosition : Vector2[];
    24. private var myPhoneTouchEndedPosition : Vector2[];
    25. private var myPhoneTouchDeltaPosition : Vector2[];
    26. private var myPhoneTouchDeltaLength : float[];
    27. private var myPhoneTouchBeganTime : float[];
    28. private var myPhoneTouchEndedTime : float[];
    29. private var myPhoneTouchDeltaTime : float[];
    30. private var myPhoneTouchVelocity : float[];
    31. private var myPhoneTouchTapCount : int[];
    32. private var myPhoneTouchPhase : iPhoneTouchPhase[];
    33. private var myPhoneTouchCount : int;
    34. private var myPhoneTouchBeganHit : boolean[];
    35. private var myPhoneTouchMovedHit : boolean[];
    36. private var myPhoneTouchEndedHit : boolean[];
    37. var Player1Began : GUIText;
    38. var Player1Ended : GUIText;
    39.  
    40. function touchInit()
    41. {
    42.     myPhoneTouchFingerId = new int[5];
    43.     myPhoneTouchBeganPosition = new Vector2[5];
    44.     myPhoneTouchEndedPosition = new Vector2[5];
    45.     myPhoneTouchDeltaPosition = new Vector2[5];
    46.     myPhoneTouchDeltaLength = new float[5];
    47.     myPhoneTouchBeganTime = new float[5];
    48.     myPhoneTouchEndedTime = new float[5];
    49.     myPhoneTouchDeltaTime = new float[5];
    50.     myPhoneTouchVelocity = new float[5];
    51.     myPhoneTouchTapCount = new int[5];
    52.     myPhoneTouchPhase = new iPhoneTouchPhase[5];
    53.     myPhoneTouchBeganHit = new boolean[5];
    54.     myPhoneTouchMovedHit = new boolean[5];
    55.     myPhoneTouchEndedHit = new boolean[5];
    56.     myPhoneTouchCount = 0;
    57.    
    58.     myPhoneTouchVelocity[0] = 0;
    59.     myPhoneTouchBeganHit[0] = false;
    60.     myPhoneTouchMovedHit[0] = false;
    61.     myPhoneTouchEndedHit[0] = false;
    62. }
    63. function touchEvents()
    64. {
    65.     if(Event.current.type == EventType.MouseDown)
    66.     {
    67.         if(eventTouchCount == 0)
    68.         {
    69.             myPhoneTouchBeganPosition[eventTouchCount] = Vector2(Event.current.mousePosition.x,480 - Event.current.mousePosition.y);
    70.             myPhoneTouchBeganTime[eventTouchCount] = Time.time;
    71.             myPhoneTouchPhase[eventTouchCount] = iPhoneTouchPhase.Began;
    72.            
    73.         }
    74.  
    75.  
    76.         Player1Began.pixelOffset.x = Event.current.mousePosition.x-160;
    77.         Player1Began.pixelOffset.y = 240 - Event.current.mousePosition.y;
    78.         eventTouchCount++;
    79.         totalTouchCount++;
    80.     }
    81.     else if(Event.current.type == EventType.MouseUp)
    82.     {
    83.         eventTouchCount--;
    84.         if(eventTouchCount == 0)
    85.         {
    86.             myPhoneTouchEndedPosition[eventTouchCount] = Vector2(Event.current.mousePosition.x,480 - Event.current.mousePosition.y);
    87.             myPhoneTouchEndedTime[eventTouchCount] = Time.time;
    88.             myPhoneTouchPhase[eventTouchCount] = iPhoneTouchPhase.Ended;
    89.             if(myPhoneTouchEndedPosition[0].x == myPhoneTouchBeganPosition[0].x  myPhoneTouchEndedPosition[0].y == myPhoneTouchBeganPosition[0].y)
    90.             {
    91.                 samePosition++;
    92.                 print("myPhoneTouchBeganPosition[0] = "+myPhoneTouchBeganPosition[eventTouchCount] + "    myPhoneTouchEndedPosition[0] = "+myPhoneTouchEndedPosition[eventTouchCount] + "tTC=" +totalTouchCount );             
    93.             }
    94.  
    95.             myPhoneTouchDeltaPosition[eventTouchCount] = myPhoneTouchEndedPosition[eventTouchCount]-myPhoneTouchBeganPosition[eventTouchCount];
    96.             myPhoneTouchDeltaLength[eventTouchCount] = myPhoneTouchDeltaPosition[eventTouchCount].magnitude;
    97.             myPhoneTouchDeltaTime[eventTouchCount] = myPhoneTouchEndedTime[eventTouchCount] - myPhoneTouchBeganTime[eventTouchCount];
    98.             myPhoneTouchVelocity[eventTouchCount] = myPhoneTouchDeltaLength[eventTouchCount]/myPhoneTouchDeltaTime[eventTouchCount];
    99.    
    100.         Player1Ended.pixelOffset.x = Event.current.mousePosition.x-160;
    101.         Player1Ended.pixelOffset.y = 240 - Event.current.mousePosition.y;
    102.     }
    103.     else if(Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag)
    104.     {
    105.        
    106.     }  
    107. }
    108.  
     
  9. Lostlogic

    Lostlogic

    Joined:
    Sep 6, 2009
    Posts:
    693
    In my first Unity project I found this to be a huge problem. I solved it by optimizing the game. It seems that if your frame rate is slow you will miss touches. I expect this is due to the reasons mentioned above (about handling once per frame.)

    The problem is actually quite annoying since the slow frame rate is something I was willing to give in return for the experience. In my situation the frame rate wasn't really a factor, but missing touches was. In the end I had to give up the "looks" of the game in return for better touch realization.
     
  10. dayglo

    dayglo

    Joined:
    Apr 28, 2010
    Posts:
    24
    I did a lot of optimizing and re-factoring, and it did seem to fix the issue.

    Although, one of the QA guys reproduced it and has assigned a programmer to work on it, which is pretty cool.

    gee
     
  11. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    missing touches also has a bit to do with which rendering loop type you use (xcode defines in AppController.mm).
    some of them are more likely to miss out touches.
     
  12. jtbentley

    jtbentley

    Joined:
    Jun 30, 2009
    Posts:
    1,397
    Dreamora is correct.. If you check your Application.mm, it's documented. Basically, you can either have awesome frame rate or awesome event accuracy. Ideally, if you're quite efficient about it all, neither should be a problem.
     
  13. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    yupp

    I've a heavily gui (actually gui layout due to the dynamics of the data) driven application in Unity iPhone 1.7 created under contract and OnGUI especially with layout is known to be heavy stuff.

    And that thing fetches data through HTTP, including 480x320 images etc that are loaded in realtime for rendering in the UI etc. The whole thing replicates stuff like ui list views with search box and I've an infinit grid of 64x64 basically.

    Thats by far no lightweight thing but once you get the datamanagement and fetching opted, it will start to get lightning fast :)

    Its all a matter of appropriate optimization in the second half of the games development.
    Its normal that during the first 50 - 75% of a project, the app might not be thaaat fast (if you are unsure about technical doability in general then more towards 50%, otherwise more towards 75%) and thus suffer such problems.

    Also Instruments and Shark are good friends for finding stupid errors ;)
     
  14. nachobeard

    nachobeard

    Joined:
    May 7, 2013
    Posts:
    47