UnityでiOS/Android/Editorの共通タッチ処理を実装する

**[UnityAsset「GodTouch」](https://tempura-kingdom.jp/godtouch/)**
↑Asset化しました☆

* * *

Unityでスマートフォンのタッチ処理を実装するには以下のようにするかと思う。

```csharp:Touch.cs
if (Input.touchCount > 0)
{
    Touch touch = Input.GetTouch(0);
    if(touch.phase == TouchPhase.Began)
    {
        // タッチ開始
    }
    else if (touch.phase == TouchPhase.Moved)
    {
        // タッチ移動
    }
    else if (touch.phase == TouchPhase.Ended)
    {
        // タッチ終了
    }
}
```

でもこれってエディタ上では動作しなくて(タッチ数が常に0)、タッチの処理を毎回実機に転送して確認ってのはダルい。。
もちろんAssetStoreから適当なタッチAssetを取ってきてもいいけど(こんなんとか→ https://assetstore.unity.com/packages/tools/input-management/fingers-touch-gestures-for-unity-41076 )、大抵の場合タッチ処理ってそんな複雑ことしなくていいから以下のようなものを使ってる。

```csharp:AppUtil.cs
public static class AppUtil
{
    private static Vector3 TouchPosition = Vector3.zero;

    /// <summary>
    /// タッチ情報を取得(エディタと実機を考慮)
    /// </summary>
    /// <returns>タッチ情報。タッチされていない場合は null</returns>
    public static TouchInfo GetTouch()
    {
        if (AppConst.IsEditor)
        {
            if (Input.GetMouseButtonDown(0)) { return TouchInfo.Began; }
            if (Input.GetMouseButton(0)) { return TouchInfo.Moved; }
            if (Input.GetMouseButtonUp(0)) { return TouchInfo.Ended; }
        }
        else
        {
            if (Input.touchCount > 0)
            {
                return (TouchInfo)((int)Input.GetTouch(0).phase);
            }
        }
        return TouchInfo.None;
    }

    /// <summary>
    /// タッチポジションを取得(エディタと実機を考慮)
    /// </summary>
    /// <returns>タッチポジション。タッチされていない場合は (0, 0, 0)</returns>
    public static Vector3 GetTouchPosition()
    {
        if (AppConst.IsEditor)
        {
            TouchInfo touch = AppUtil.GetTouch();
            if (touch != TouchInfo.None) { return Input.mousePosition; }
        }
        else
        {
            if (Input.touchCount > 0)
            {
                Touch touch = Input.GetTouch(0);
                TouchPosition.x = touch.position.x;
                TouchPosition.y = touch.position.y;
                return TouchPosition;
            }
        }
        return Vector3.zero;
    }

    /// <summary>
    /// タッチワールドポジションを取得(エディタと実機を考慮)
    /// </summary>
    /// <param name='camera'>カメラ</param>
    /// <returns>タッチワールドポジション。タッチされていない場合は (0, 0, 0)</returns>
    public static Vector3 GetTouchWorldPosition(Camera camera)
    {
        return camera.ScreenToWorldPoint(GetTouchPosition());
    }
}

/// <summary>
/// タッチ情報。UnityEngine.TouchPhase に None の情報を追加拡張。
/// </summary>
public enum TouchInfo
{
    /// <summary>
    /// タッチなし
    /// </summary>
    None = 99,

    // 以下は UnityEngine.TouchPhase の値に対応
    /// <summary>
    /// タッチ開始
    /// </summary>
    Began = 0,
    /// <summary>
    /// タッチ移動
    /// </summary>
    Moved = 1,
    /// <summary>
    /// タッチ静止
    /// </summary>
    Stationary = 2,
    /// <summary>
    /// タッチ終了
    /// </summary>
    Ended = 3,
    /// <summary>
    /// タッチキャンセル
    /// </summary>
    Canceled = 4,
}
```

ついでに UnityEngine.TouchPhase 列挙型にタッチなし状態がなかったので追加。これでタッチ数気にせず GetTouch() で TouchInfo さえ取得すればタッチ判定を処理可能。

```csharp:SceneStart.cs
// 以前はこう書いてたのを・・・
if(Input.touchCount > 0)
{
    Touch touch = Input.GetTouch(0);
    if(touch.phase == TouchPhase.Began)
    {
        // タッチ開始
    }
}

// こう書ける
TouchInfo info = AppUtil.GetTouch();
if (info == TouchInfo.Began)
{
    // タッチ開始
}
```

うん、スマート