Mobile device input

From ETC Public Wiki
Jump to: navigation, search

Overview

You can get most mobile device input data by accessing Input in Unity3D. Please refer to Unity Input for basic info. Here we just talk about some practices and tricks for these input.


Multi-touch

To get multi-touch data, you can access Input.touches for an array of touch info. See here for touch info structure.
Please not this structure is read only, you cannot create a new Touch instance. If you reach a stage that you need to pass in a "fake" touch info (simulator for example), consider writing your own touch structure to wrap it up.
Unity does not have functions like "OnMouseDown", "OnMouseUp" for touches, but sometime it is convenient to have them. Here Locomobio provides simple way to make this happen:
You need a "TouchDispatcher" script attached to a GameObject, and never get destroyed until you don't need touch functions anymore.

   rayCastRange = 100;
   layerMask = 1 << LayerMask.NameToLayer("TouchInputObject");
   void Update () {
       for(Touch touch in Input.touches) {
           switch(touch.phase) {
           case TouchPhase.Began:
               TriggerInputEvent(new Vector3(touch.position.x, touch.position.y, 0), "OnTouchDown", touch);
               break;
           case TouchPhase.Ended:
               TriggerInputEvent(new Vector3(touch.position.x, touch.position.y, 0), "OnTouchUp", touch);
               break;
           case TouchPhase.Moved:
           case TouchPhase.Stationary:	
               TriggerInputEvent(new Vector3(touch.position.x, touch.position.y, 0), "OnTouch", touch);
               break;
           }
       }
   }
   private void TriggerInputEvent(Vector3 pos, string eventStr, System.Object message) {
       GameObject hitObj = GetNearestHitGameObject(pos);
       if(hitObj != null) {
           hitObj.SendMessage(eventStr, message,SendMessageOptions.DontRequireReceiver);
       }
   }
   private GameObject GetNearestHitGameObject(Vector3 pos) {
       Ray ray = Camera.main.ScreenPointToRay(pos);
       RaycastHit[] hitInfos = Physics.RaycastAll(ray, rayCastRange, layerMask);
       if(hitInfos.Length == 0) {
           return null;
       }
       RaycastHit nearestHit;
       float minDist = float.MaxValue;
       foreach(RaycastHit hit in hits) {
           if(hit.distance < minDist) {
               minDist = hit.distance;
               nearestHit = hit;
           }
       }
       return nearestHit.collider.gameObject;
   }

The script will cast a ray from the touch point to the first hit gameobject with "TouchInputObject" layer within 100 units, and call corresponding functions (OnTouchDown, OnTouchUp and OnTouch) of the scripts on that gameobject.

  • Please change rayCastRange according to the scale or your world, but don't make it too large for performance reason.
  • Usually you want to define a layerMask for raycast, one is for better performance, another is your decoration objects over a button will get passed through and your ray will hit the "real" button with that specific layer.
  • If you want every gameobject get hit by the ray be triggered, instead of getting nearest gameobject, simply fire them all.
  • With similar structure you can play with more stuff, like swipe, touch move in/out of a button. You may need to store some more temporal info for that.


Location Input

From Unity 3.5, location input get merged into unified input interface Input. Access to Input.location start, stop or get location info. See here for details.

  • Before you access location data, you need to call Input.location.Start() to start location service. Here you can pass in accuracy parameters, see Unity documentation for more descriptions. Please note this process takes time. You should keep checking Input.location.lastData.status until it turns to LocationServiceStatus.Running.
  • You can stop location service by calling Input.location.Stop(). Location service consumes battery quickly, so please turn it off if you don't need it.
  • Notice that LocationServiceStatus.Running status does not guarantee you the correct location info. It just means the services successfully initialized and started (It fails usually because user has turned this function off). If GPS signal got lost when you are in a tunnel for example, this status does not change. Do NOT rely on this status, use other method to check the correctness of your location.


Gyroscope

Access to Input.gyro to get gyroscope data. See here for details.

  • You need to set Input.gyro.enabled = true to enable the service.


Vibration

It is not input but it is reasonable to be here. Check out here for vibration.