search
LoginSignup
2

More than 3 years have passed since last update.

posted at

updated at

Unity2D でジェスチャー操作(ピンチ操作、スワイプ操作)のスクリプトを作った。

さいしょに

Unity2Dでスマホ用アプリを作る際にピンチイン、ピンチアウト(つまりズーム)やスワイプを実装したかった。
ピンチ操作の場合、指同士の中心位置を拡大・縮小したかったがコードが見つからず。(単に検索力のNASA)

参考にした記事

Unityでピンチイン・ピンチアウトを実装する

感謝いたします。

環境

  • Unity 2018.2.9f1 Personal (64bit)
  • Xperia XZ Premium (Android 7.1.1)
  • Microsoft Visual Studio

iPhone(iOS)も調べてみたいけど持っておらず。

コード

Gesture.cs
using UnityEngine;
using System.Collections;

public class Gesture : MonoBehaviour
{

    //カメラの設定
    private GameObject Object;
    private Camera cam;

    //カメラ範囲の設定
    public float maxCamSize = 9.0f;
    public float minCamSize = 3.0f;
    public float maxCamX = 81.0f / 16.0f;
    public float minCamX = -81.0f / 16.0f;
    public float maxCamY = 9.0f;
    public float minCamY = -9.0f;

    //直前の指同士の距離
    private float lastDist = 0.0f;

    //指同士の中心座標
    private Vector2 centerPos;

    private Vector3 t1;
    private Vector3 t;

    //一本指タッチしたワールド座標
    private Vector2 lastTouchWorld;
    private Vector2 nowTouchWorld;

    //直前の触れている指の数
    private int lastCount = 0;

    //スピード調整
    public float zoomSpeed = 1.0f;
    public float moveSpeed = 1.0f;

    //カメラサイズの差分
    float sizeDiff;

    //カメラが画面外を映さないように処理
    void CameraSlide()
    {
        if (cam.transform.position.x > maxCamX - cam.orthographicSize * 9 / 16)
        {
            cam.transform.position = new Vector3(maxCamX - cam.orthographicSize * 9 / 16, cam.transform.position.y, cam.transform.position.z);
        }
        if (cam.transform.position.x < minCamX + cam.orthographicSize * 9 / 16)
        {
            cam.transform.position = new Vector3(minCamX + cam.orthographicSize * 9 / 16, cam.transform.position.y, cam.transform.position.z);
        }
        if (cam.transform.position.y > maxCamY - cam.orthographicSize)
        {
            cam.transform.position = new Vector3(cam.transform.position.x, maxCamY - cam.orthographicSize, cam.transform.position.z);
        }
        if (cam.transform.position.y < minCamY + cam.orthographicSize)
        {
            cam.transform.position = new Vector3(cam.transform.position.x, minCamY + cam.orthographicSize, cam.transform.position.z);
        }

    }

    void Start()
    {
        //カメラを設定
        Object = GameObject.Find("Main Camera");
        cam = Object.GetComponent<Camera>();
        cam.orthographicSize = 9f;
    }

    void Update()
    {
        //タッチが0
        if (Input.touchCount == 0)
        {
            lastCount = 0;
        }
        //スワイプ操作(直前のtouchCountを1以下にすることでピンチ操作後に反応しないようにしています。)
        else if (Input.touchCount == 1 && lastCount <= 1)
        {
            //タッチ位置取得
            Touch touch3 = Input.GetTouch(0);

            //触れたとき
            if (touch3.phase == TouchPhase.Began)
            {
                t = touch3.position;
                lastTouchWorld = cam.ScreenToWorldPoint(t);
            }
            //動いたら
            else if (touch3.phase == TouchPhase.Moved)
            {
                //前回の座標を保存
                nowTouchWorld = lastTouchWorld;
                //今の座標を保存
                t = touch3.position;
                nowTouchWorld = cam.ScreenToWorldPoint(t);
                //カメラを移動
                cam.transform.position = new Vector3(cam.transform.position.x + (lastTouchWorld.x - nowTouchWorld.x) * moveSpeed, cam.transform.position.y + (lastTouchWorld.y - nowTouchWorld.y) * moveSpeed, cam.transform.position.z);

                CameraSlide();
            }

            lastCount = 1;
        }
        //ピンチ操作
        else if (Input.touchCount >= 2)
        {
            //タッチ位置取得
            Touch touch1 = Input.GetTouch(0);
            Touch touch2 = Input.GetTouch(1);

            //二本目が触れたとき
            if (touch2.phase == TouchPhase.Began)
            {
                //指同士の距離と中心座標を取得
                lastDist = Vector2.Distance(touch1.position, touch2.position);
                centerPos = (touch1.position + touch2.position) * 0.5f;
                centerPos = cam.ScreenToWorldPoint(centerPos);
            }
            //どちらかの指が動いたら
            else if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved)
            {
                //指同士の距離を計算
                float newDist = Vector2.Distance(touch1.position, touch2.position);

                //ズーム処理
                sizeDiff = cam.orthographicSize * cam.orthographicSize * (newDist - lastDist) / 10000.0f * zoomSpeed;
                cam.orthographicSize -= sizeDiff;


                //カメラが拡大(縮小)しすぎた場合の制限
                if (cam.orthographicSize > maxCamSize)
                {
                    cam.orthographicSize = maxCamSize;
                }
                else if (cam.orthographicSize < minCamSize)
                {
                    cam.orthographicSize = minCamSize;
                }
                //指同士の中心位置がピンチ操作の中心となるようにカメラを平行移動
                else
                {
                    cam.transform.position = new Vector3(centerPos.x + cam.orthographicSize / (cam.orthographicSize + sizeDiff) * (cam.transform.position.x - centerPos.x), centerPos.y + cam.orthographicSize / (cam.orthographicSize + sizeDiff) * (cam.transform.position.y - centerPos.y), cam.transform.position.z);
                }
                CameraSlide();
            }
            lastCount = 2;
        }
    }
}

所感

カメラサイズ9, 画面解像度1080x1960(アスペクト比9:16)に設定しています。
違う設定の場合は値を変更してください。

ピンチ操作のとき、線形にカメラサイズ変更するとカメラサイズが小さいとき(拡大率が大きいとき)ズームの速度が大きくなってしまうので、カメラサイズが小さくなるとズームも遅くなるように二次関数的な値に変更しています。

UnityとC#始めて1週間なのでコードが汚いかも。
もっとスマートなコードがあれば教えていただけると嬉しいです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2