12/31/13

Touch Events in Unity3D

I’ve been working on Crazy Bugz for the past few days to take advantage of the 2D physics and sprites brought in by the latest version of Unity3D. Many things have been updated which reserves a post all by itself. For now, I want to discuss a discovery I made regarding the touch events. I’m not sure if this is iOS or Unity3D specific but I’ve built a work around that seems to be working for now šŸ˜€

For a demonstration, here’s a Unity3D packageĀ (requires 4.3). Build and test it on touch devices. I’ve only tested it for iOS devices. You can test it with Unity Remote but it has limitations like touch responsiveness which is critical for this demonstration.

TouchDemo
TouchDemo
TouchDemo.unitypackage
14.3 KiB
812 Downloads
Details

First and foremost, I made a generic event handler for the different touch phases in TouchMonoBehavior.cs

The OnTouch* event handlers are all declared public virtual void and passes the Touch parameter. Meaning, each event handler could be called multiple times per Update() depending on how many touches there are (Input.touchCount). We can treat each touch separately by taking note of the finger id that comes with the touch.

All the while, I thought the touch phases have the following state diagram

Touch Phases State Diagram

Unfortunately, upon testing over and over again, it is POSSIBLE to start with Moved or Ended! I haven’t noticed if it could start with Stationary since I don’t use it for my projects at the moment. But my point here is that the Began phase CAN BE SKIPPED! I’m not sure if this is intentional but it’s happening and it got me pulling my hair for the past couple of days.

I’m using an object pool in my project where the objects react to touch. When the user touches, an object is created, let’s call that Object 0. When the user touches again, another object is created called Object 1. If Object 0 gets disabled (as part of the game mechanic) and the user touches again, Object 0 will be re-intialized and treated as something new. Objects don’t get destroyed, rather, they become disabled. This is basically how object pooling works.

Theoretically, every time a BeganĀ phase is encountered, a mirror is re-initialized in Crazy Bugz. The user can rotate or stretch this mirror by moving their finger which corresponds to theĀ Moved phase. When the user releases their finger, anĀ Ended phase is encountered and that mirror remains enabled until it gets disabled (shattered) by the laser. However, there are certain occasions where I touch and get a NullExceptionError. It turns out, my game is trying to look for a mirror with a specified finger id that was not created. This means, theĀ Began phase was skipped!

As a work around, if in case the Began phase has been skipped and goes directly to Moved phase, I would treat that as a Began phase. In the case the Began phase has been skipped and goes directly to Ended, I would simply ignore it.

Not exactly the best solution but this will have to do.

The ideal case? Well, Began phase shouldn’t be skipped… ever šŸ™‚