Unity 3D: Working with touch input

In this tutorial we'll walk through how to handle single and multi-touch input in Unity. Note that this tutorial is based on Unity 4. The scripts have been written and tested on version 4.5.1. As major releases are distributed, Unity API may change or behave differently, and new functionalities may be added.

Detecting touches

Here, we'll use the Input class to detect, count and retrieve touches. First of all, we can check whether the current device supports multi-touch input using this flag:

 
 
  1.    bool supportsMultiTouch = Input.multiTouchEnabled;
  2.    print("MultiTouchSupport : " + supportsMultiTouch);

For the purpose of this tutorial we'll assume that multi-touch is supported. The only difference is that, for single-touch devices, you'll only get one touch input at a time.

For example, here we detect all current touches and their position:

 
 
  1. void Update ()
  2.     {
  3.         int nbTouches = Input.touchCount;
  4.         if(nbTouches > 0)
  5.         {
  6.             print(nbTouches + " touch(es) detected");
  7.             for (int i = 0; i < nbTouches; i++)
  8.             {
  9.                 Touch touch = Input.GetTouch(i);
  10.                 print("Touch index " + touch.fingerId + " detected at position " + touch.position);
  11.             }
  12.         }
  13. }

Input.touchCount defines how many touches are detected in the current frame. We can then loop and use Input.GetTouch to retrieve all touches.

Each Touch struct has a fingerId, which identifies the instance for its lifetime, until the touch stops. This can be used to identify the same touch on different frames.

touch.position defines the coordinates of that touch in the screen. Remember that the origin of the axis is on the lower left corner of the screen.

Another method to retrieve touches is through Input.touches, which returns a list of current touches objects. The first method should be preferred though, as Input.touches allocates temp variables and could impact your game's performance.

Input data is refreshed every frame, right before Update(), so that's where you should put all input-management logic. Doing so somewhere else, like in FixedUpdate, would prevent you from catching all input from the user, as FixedUpdate is not called every frame but on fixed steps.

Touch Phases

When dealing with Touch input, it's useful to know whether the touch has just started, ended or if it's swiping in the screen. To do so, we can use the phase property:

 
 
  1. void Update ()
  2. {
  3.    int nbTouches = Input.touchCount;
  4.    if(nbTouches > 0)
  5.    {
  6.       for (int i = 0; i < nbTouches; i++)
  7.       {
  8.          Touch touch = Input.GetTouch(i);
  9.          TouchPhase phase = touch.phase;
  10.          switch(phase)
  11.          {
  12.             case TouchPhase.Began:
  13.                print("New touch detected at position " + touch.position + " , index " + touch.fingerId);
  14.                break;
  15.             case TouchPhase.Moved:
  16.                print("Touch index " + touch.fingerId + " has moved by " + touch.deltaPosition);
  17.                break;
  18.             case TouchPhase.Stationary:
  19.                print("Touch index " + touch.fingerId + " is stationary at position " + touch.position);
  20.                break;
  21.             case TouchPhase.Ended:
  22.                print("Touch index " + touch.fingerId + " ended at position " + touch.position);
  23.                break;
  24.             case TouchPhase.Canceled:
  25.                print("Touch index " + touch.fingerId + " cancelled");
  26.                 break;
  27.             }
  28.         }
  29.    }
  30. }

When the user is swiping his finger on the screen, we track the delta position instead of the actual position, which may be useful in case you want to drag stuff in games using touch input. We can then use deltaTime to calculate the moving speed of the touch input:

 
 
  1. float touchSpeed = touch.deltaPosition.magnitude / touch.deltaTime;

A touch is marked as cancelled when the system assumes it has been done by mistake, for example when a large area is pressed against the screen, or when more touches than the device can support are detected.

To detect whether the user has tapped on something, we first check if the touch phase is “Began.” Then, we can cast a ray from the input position using the camera, and then check any Raycast collision against that ray

 
 
  1. void Update ()
  2.     {
  3.         int nbTouches = Input.touchCount;
  4.         if(nbTouches > 0)
  5.         {
  6.             for (int i = 0; i < nbTouches; i++)
  7.             {
  8.                 Touch touch = Input.GetTouch(i);
  9.                 if(touch.phase == TouchPhase.Began)
  10.                 {
  11.                     Ray screenRay = Camera.main.ScreenPointToRay(touch.position);
  12.                     RaycastHit hit;
  13.                     if (Physics.Raycast(screenRay, out hit))
  14.                     {
  15.             print("User tapped on game object " + hit.collider.gameObject.name);
  16.                         handleTap(hit.collider.gameObject);
  17.                     }
  18.                 }
  19.             }
  20.         }
  21. }

In some cases, we want to do different things if the user is quickly tapping in the screen. For example, we may tell our player to walk when you tap on the screen, but run if you quickly double-tap:

 
 
  1. void Update ()
  2.     {
  3.         int nbTouches = Input.touchCount;
  4.         if(nbTouches > 0)
  5.         {
  6.             for (int i = 0; i < nbTouches; i++)
  7.             {
  8.                 Touch touch = Input.GetTouch(i);
  9.                 if(touch.phase == TouchPhase.Began)
  10.                 {
  11.                     if(touch.tapCount >= 2)
  12.                     {
  13.                         Run();
  14.                     }
  15.                     else
  16.                     {
  17.                         Walk();
  18.                     }
  19.                 }
  20.             }
  21.         }
  22.         else
  23.         {
  24.             StopMoving();
  25.         }
  26. }

When a touch begins, the player will start walking on a single tap, or running if it was a multi-tap. The game character will stop moving if no touches are detected. When implementing the different methods, Walk for example, you'll also want to check if the user is already walking.

In some cases, Unity will not be able to distinguish whether you're quickly tapping with the same finger or with two different fingers in succession, so keep that in mind.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值