Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by pcreation · Oct 02, 2012 at 02:16 PM · touchgettouch

Strange touch behavior?

Strange touch behavior?

I have some code below and I cannot seem to work out where I am going wrong. Have spent the good part of two weeks testing many different combinations and I am starting to pull out when little hair I have left. Any help much appreciated.

I am trying to reliably spawn a prefab and get it to track under a finger position and when finger removed the prefab is destroyed. To do this I setup a prefab with a script that has a finger ID set when Instantiated. This ID is used to track the specific finger. Its also used to destroy the prefab if the same ID is matched with the fingerIDActive array.

Main Game Script

 #pragma strict
 var fingerPointPrefab : GameObject;
 static var maxTouches : int = 11;
 static var touchPos : Vector2[];
 static var fingerIDActive : int[];
 private var touchPhase : TouchPhase[];
 
 function Start()
 {
     touchPos = new Vector2[ maxTouches ];
     touchPhase = new TouchPhase[ maxTouches ];
     fingerIDActive = new int[ maxTouches ];
 }
 
 function Update () {
     var count = Input.touchCount;
     
     for ( var i : int = 0;i < count; i++) {
         var touch : Touch = Input.GetTouch( i );
         var figID = touch.fingerId;
         
         // Cache touch data.
         touchPos[ figID ] = touch.position;
         touchPhase[ figID ] = touch.phase;    
         
         // End finger marker 
         if (touchPhase[ figID ] == TouchPhase.Ended){ 
              fingerIDActive[ figID ] = 0;
         }
         
         // Spawn finger marker 
         if ((touchPhase[ figID ] == TouchPhase.Began) && (fingerIDActive[ figID ] == 0)){  
             Instantiate(fingerPointPrefab, touch.position, Quaternion.identity);
             fingerPointPrefab.GetComponent(JSFingerTracker).finderNumber = figID;
             var PFname: String = ("FingerID" + figID);
             fingerPointPrefab.name = PFname;
             fingerIDActive[ figID ] = 1;
         }
     }
 }



Prefab Script

 #pragma strict
 var finderNumber : int = 0;
 private var fingerPos: Vector3;
 private var worldPos: Vector3;
 
 function Update () {
     fingerPos = JSGameControler.touchPos[ finderNumber ];
     fingerPos.z = 10;
     worldPos = Camera.main.ScreenToWorldPoint(fingerPos);
     transform.position = worldPos;
 
     if (JSGameControler.fingerIDActive[finderNumber] == 0) {
         Destroy(gameObject);
     }    
 }


Expected behavior: Should create a prefab under finger, track finger when moved and if finger removed the prefab should be destroyed.

Observed behavior: (When compiled on iPad1) Prefabs are not spawned or destroyed reliably. Many times when an additional finger is added, the previous finger placed gets its prefab spawned correctly under it. And this is the strangest behavior and does not seem to happen 100% but it seems the more fingers you place down the more you get random jittering. This seems to get worse when fingers are placed in a line horizontally on the iPad when held in landscape mode. This gets so bad that they pop all over the screen appearing and disappearing randomly. Have even seen it spawning phantom finger points. Maybe my iPad is possessed!! lol

Note, I am fairly new to JavaScript and still have much to learn.

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Fattie · Oct 02, 2012 at 02:46 PM 0
Share

in short, don't instantiate, use a simple array (or maybe a pool)...

http://answers.unity3d.com/questions/321762/how-to-assign-variable-to-a-prefabs-child.html

regarding accurately dealing with glass V. real world measurements

http://answers.unity3d.com/questions/292333/how-to-calculate-swipe-speed-on-ios.html

Regarding the actual process of handling many fingers and putting a red cube under each finger, explained in long answer below.

2 Replies

· Add your reply
  • Sort: 
avatar image
10
Best Answer

Answer by Fattie · Oct 02, 2012 at 03:23 PM

This may help .. drop this on something and run.

Play with three fingers on the screen .. it might help demonstrate what the hell is going on!

 function Update()
     {
     
     if ( Input.touches.Length == 1 )
         Debug.Log("    " +Input.touches[0].fingerId);
     
     if ( Input.touches.Length == 2 )
         Debug.Log("    " +Input.touches[0].fingerId
                 +"    " +Input.touches[1].fingerId
                 );
     
     if ( Input.touches.Length == 3 )
         Debug.Log("    " +Input.touches[0].fingerId
                 +"    " +Input.touches[1].fingerId
                 +"    " +Input.touches[2].fingerId
                 );
     
     }


Next step!

Next step you have to process each touch based on it's Unity touchId:

 function Update()
     {
     for ( var t:int=0; t<Input.touches.Length; ++t )
         processATouchPerFingerCodeNumber(
               Input.touches[t], Input.touches[t].fingerId );
     }

So in the next function you have a touch to deal with, and it's Unity code number. Try this code, and extensively play with your iPad. You will really see how it works, it's great.

 function processATouchPerFingerCodeNumber( t:Touch, n:int )
     {
     
     if ( t.phase == TouchPhase.Began )
         {
         Debug.Log("A finger has ARRIVED.  it's arbitrary +"
                     "code number is: " + n);
         return;
         }
     if ( t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled )
         {
         Debug.Log("Well that's it. A finger went away .. being "+
                     "arbitrary code number: " + n);
         Debug.Log("(Don't get confused .. the code numbers "+
                     will be resued, perhaps immediately.)");
         return;
         }
     
     // you can also process .Moved and/or .Stationary here
     }

when you have that down, add this clause to the processing function

 if ( t.phase == TouchPhase.Moved )
     {
     Debug.Log("You moved this finger: " + n);
     return;
     }


Now it, carefully moving one finger at a time.

OK so you've got that. Now here's an important point. On many systems those id numbers are just arbitrary, like 343243. (Or you don't even get an id number, it's just a pointer.)

So let's say it was 343243. Now, you have an array of say ten of the image of the red spot - you want to put a red spot under each finger.

Again - the next id number happens to be 343243, and you ave the array of ten.

So what you have to do is, take the "first available" red spot image in the array of red spot images. Let's say it's number 2 currently. So, you have to associate "343243" with YOUR array item 2. (Using a dictionary, lookup, whatever.)

Next time when processATouchPerFingerCodeNumber is called, and the number is "343243" THEN, IN FACT, you have to "look up" what your number it is. (In fact 2 in the example.)

So that's what you normally have to do ...


BUT ......

very conveniently, Unity ensures thas the id code numbers, will run from 0-10. (I"m not sure what the max is on different platforms, but it doesn't matter. YOU should impose a maximum of six, ten or however many fingers you wish to be the maximum.)

Again NORMALLY you MUST do a mapping between the CODE NUMBER (say 424234) and your OWN array (which runs from 0 to 9.)

BUT VERY HAPPILY in the specific Unity case, you don't need to do that. Because Unity guarantees to recycle them, and they always stay below 10, you can and should ...... SIMPLY USE THAT ID NUMBER, as your own array number.

So in short, your code for processATouchPerFingerCodeNumber will look precisely like this.

 function processATouchPerFingerCodeNumber( t:Touch, n:int )
     {
     
     if ( t.phase == TouchPhase.Began )
         {
         // a new finger has arrived!  fortunately WE KNOW it's
         // perfectly OK here in Unity to simply use that same number,
         // "our" array. in most systems, at this stage you would
         // "find an empty slot" and make a note of the mapping from
         // 424341 (or whatever) to our slot. again Unity GUARANTEES
         // to recycle them and always stays low so it is absolutely
         // OK to use it. but it's extremely important to realize
         // you can't normally do this - it's just Unity!!
         
         if ( t >= 7 ) return;
         // we enforce a maximum of seven (say) images, if someone
         // puts more than that many fingers on the screen, they can
         // go to hell
         
         myImages[ t ].showTheImageNow();
         myImages[ t ].positionImageAt( t.position );
         // it's that easy
         return;
         }
     if ( t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled )
         {
         myImages[ t ].hideTheImageNow();
         // it's that easy
         return;
         }
     if ( t.phase == TouchPhase.Moved )
         {
         myImages[ t ].positionImageAt( t.position );
         // it's that easy
         // nb as with any touch code, it's always tricky to know
         // how much to move it, you may have to convert from glass
         // to real world, scale, do a raycast, whatever.
         return;
         }
     
     // you can also process .Stationary here if relevant,
     // perhaps spin it or whatever is relevant to you
     }

Hopefully this helps you or someone else reading. Cheers.

Comment
Add comment · Show 16 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlucardJay · Oct 02, 2012 at 04:37 PM 0
Share

from memory, any more than 5 Input.touches nullifies all those inputs and all the previous touches are assigned TouchPhase.Cancelled

Upvoted for another awesome informative answer.

avatar image gregzo · Oct 02, 2012 at 04:55 PM 0
Share

@alucardj Hmmm, not sure you're right there. I've done stuff with 6 different touches on the iPad without any problems.

avatar image AlucardJay · Oct 02, 2012 at 05:00 PM 0
Share

Wow, thanks. $$anonymous$$y information was for phone, but a quick search reveals you are both correct for iPad (I never doubted it really!) :

http://mattgemmell.com/2010/05/09/ipad-multi-touch/

http://stackoverflow.com/questions/1202484/how-to-force-iphone-ipod-touch-to-handle-more-than-5-touches-at-the-same-time

http://stackoverflow.com/questions/3149868/deter$$anonymous$$ing-the-maximum-number-of-simultaneous-touches-possible-on-an-ios-device

avatar image pcreation · Oct 02, 2012 at 05:29 PM 0
Share

Thank you so much for your swift and informative answer. I feel I need to go back to the drawing board. There is so much more code I cobbled together that needs to be thrown away. Wish I had asked the question a bit earlier, its all good learning though :) Thank you

avatar image Fattie · Oct 03, 2012 at 01:44 PM 1
Share

right -- I know just what you mean.

it's actually very hard to do this ...

myImages[ t ].showTheImageNow();

don't do it ! Heh !!!!!!!! If you like start a NEW question asking just that and you'll get vast answers.

please just do this:

 function showOneImageNow( whichImageNumber:int );

or you may need something like

 function showImageAtPosition( whichImageNumber:int, p:Vector3 );

"where best to put code" .. make many small functions, all in one big script. it's that simple.

you mention the st*tic keyword. Never - ever - EVER use the static keyword. If you are using it now, delete it. so forget that was ever mentioned!

now, your one big script may get a little too big....

if so you can make two (or more) different scripts

to get from one to the other is incredibly simple

GetComponent( otherScriptName )

so to call a function in another script

GetComponent( OtherScriptName ).showFireworksNow()

to get to a script ON A DIFFERNT OBJECT is very simple

GameObject.Find("potato)").GetComponent(SomeScriptName);

really the doco is very good on this. go to unity, doco, scriptin, basics.

cheers!

Show more comments
avatar image
2

Answer by mr-eaves · Jan 28, 2013 at 04:20 PM

The bit about Unity clamping to 0 - 9, it doesn't at all.

Do a simple Android app just to print out the ID's, press however many fingers on the screen, say 5 so you get ID's 0 - 4. Hit the home button, then go back into the app again, you'll see the ID's are now 5 - 9, keep doing this with 5 fingers, and it will keep increasing.

So it is a bit of a pain really.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Jan 28, 2013 at 04:41 PM 1
Share

Well, that's a very unusual case to suspend the app while you hold fingers down. If the app is completely restarted it's cleared again.

Of course when the Touch ended events occure while the app is suspended, Unity has no chance of getting notified about that.

Btw, if you stack the ids up to ~20 it seems that GUI buttons don't work anymore ;) It's actually a nasty bug, but again a very rare case.

avatar image mr-eaves · Jan 28, 2013 at 08:19 PM 0
Share

You don't need to keep your fingers held down. Just touch the screen with 5 fingers to generate 5 touches. Remove your fingers, wait a few seconds if you like. Hit the home button to come back to the OS, the resume the app, you'll find that the touch ids will now have moved on by 5.

avatar image mr-eaves · Feb 04, 2013 at 12:31 PM 0
Share

Any more information on this? it is annoying that the FingerID's get messed up when the app is paused and resumed.

avatar image Andy-Block · Feb 12, 2013 at 01:23 PM 0
Share

Just wanted to verify that we're seeing the same behaviour reported by mr-eaves. Just tap with two fingers (and release), then return to the home screen, then back to your unity app. All the fingerIds will be 2 & 3; do the same and you start getting 4&5, and so on (past 10; I got up to 13). This is using 4.0.1f2 (on a Samsung Galaxy SII running Android 4.0.3)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

17 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Count a touch in half of screen 2 Answers

2D Raycast touch 1 Answer

Transitioning from different number of touches causes behavior overlap 0 Answers

Touches, fingerID's and changing them. 1 Answer

Please help. Attempting touch controls but I cant figure out what I'm doing wrong 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges