iOS対応

【Unity×iOS】スワイプ・フリック操作を実装する方法|Swipe & Flick 完全ガイド

スマホゲームでキャラクターを移動させたりメニューを開いたりする際、スワイプ(Swipe)フリック(Flick)は欠かせない操作です。
この記事では、Unity標準Input/新Input System/UIイベント/iOSネイティブプラグイン の4つの手法を使って、簡単にスワイプ&フリックを検出・活用する方法を解説します。すべてコピペで実装可能です!

この記事で分かること

  • Unity標準 Input.GetTouch を使ったスワイプ&フリックの基本検出
  • コピペOKの汎用SwipeDetectorスクリプト例
  • 新Input System(EnhancedTouch)で高速&複数指スワイプ対応
  • UI要素(EventTrigger / IPointerDragHandler)でのドラッグ&スワイプ検出
  • iOSネイティブのUIGestureRecognizerを用いた高精度フリック連携

Unity標準Inputでスワイプ&フリックを検出

基本のタッチ開始・終了を取得

  • swipeThreshold:最低移動距離(ピクセル)
  • flickMinDistance:フリック判定最低距離
  • flickMaxTime:フリック判定最大時間(秒)
void Update()
{
    if (Input.touchCount == 0) return;

    Touch t = Input.GetTouch(0);
    if (t.phase == TouchPhase.Began)
    {
        startPos = t.position;
        startTime = Time.time;
    }
    else if (t.phase == TouchPhase.Ended)
    {
        Vector2 endPos = t.position;
        float   deltaTime = Time.time - startTime;
        Vector2 diff = endPos - startPos;

        // スワイプ検出
        if (diff.magnitude >= swipeThreshold)
        {
            Vector2 dir = diff.normalized;
            OnSwipe(dir);
        }
        // フリック(高速スワイプ)検出
        else if (diff.magnitude >= flickMinDistance && deltaTime <= flickMaxTime)
        {
            Vector2 dir = diff.normalized;
            OnFlick(dir);
        }
    }
}

汎用SwipeDetectorスクリプト

・使い方
 本スクリプトを任意のGameObjectにアタッチ
 OnSwipe / OnFlick にコールバックを登録

using UnityEngine;
using System;

public class SwipeDetector : MonoBehaviour
{
    public float swipeThreshold    = 50f;
    public float flickMinDistance  = 100f;
    public float flickMaxTime      = 0.3f;

    private Vector2 startPos;
    private float   startTime;

    public Action<Vector2> OnSwipe;  // スワイプ方向
    public Action<Vector2> OnFlick;  // フリック方向

    void Update()
    {
        if (Input.touchCount == 0) return;
        Touch t = Input.GetTouch(0);

        switch (t.phase)
        {
            case TouchPhase.Began:
                startPos  = t.position;
                startTime = Time.time;
                break;

            case TouchPhase.Ended:
                Vector2 endPos   = t.position;
                float   deltaT   = Time.time - startTime;
                Vector2 diff     = endPos - startPos;
                float   distance = diff.magnitude;

                if (distance >= swipeThreshold)
                {
                    OnSwipe?.Invoke(diff.normalized);
                }
                if (distance >= flickMinDistance && deltaT <= flickMaxTime)
                {
                    OnFlick?.Invoke(diff.normalized);
                }
                break;
        }
    }
}

新Input System+EnhancedTouchでマルチタッチ&高速スワイプ

パッケージ設定

  1. Edit > Project Settings > Player で Active Input Handling = Both
  2. Window > Package Manager から Input System を導入

EnhancedTouchサンプル

  • finger.index:指ごとのID
  • 画面比率で閾値を設定すると解像度差を吸収できます
using UnityEngine;
using UnityEngine.InputSystem.EnhancedTouch;
using TouchPhase = UnityEngine.InputSystem.TouchPhase;
using Finger     = UnityEngine.InputSystem.EnhancedTouch.Finger;
using System;

public class EnhancedSwipeDetector : MonoBehaviour
{
    public float swipeThreshold   = 0.2f; // 画面比率
    public float flickMaxTime     = 0.2f;

    public Action<int, Vector2> OnSwipe; 
    public Action<int, Vector2> OnFlick; 

    void OnEnable()  => EnhancedTouchSupport.Enable();
    void OnDisable() => EnhancedTouchSupport.Disable();

    void Update()
    {
        foreach (Finger finger in Touch.activeFingers)
        {
            var touch = finger.currentTouch;
            if (touch.phase == TouchPhase.Ended)
            {
                Vector2 start = finger.startScreenPosition;
                Vector2 end   = touch.screenPosition;
                float   dt    = touch.time - finger.startTime;
                Vector2 diff  = end - start;
                float   ratio = diff.magnitude / Screen.height;

                if (ratio >= swipeThreshold)
                    OnSwipe?.Invoke(finger.index, diff.normalized);

                if (ratio >= swipeThreshold && dt <= flickMaxTime)
                    OnFlick?.Invoke(finger.index, diff.normalized);
            }
        }
    }
}

UIでドラッグ&スワイプを取る(EventTrigger / IPointerDragHandler)

 EventTriggerを使う場合は、InspectorでBeginDrag/EndDragイベントに本メソッドを紐付け可能。

using UnityEngine;
using UnityEngine.EventSystems;

public class UISwipeHandler : MonoBehaviour,
    IBeginDragHandler, IDragHandler, IEndDragHandler
{
    Vector2 startPos;
    float   startTime;

    public float swipeMinDistance = 50f;
    public float flickMaxTime     = 0.3f;

    public void OnBeginDrag(PointerEventData e)
    {
        startPos  = e.position;
        startTime = Time.time;
    }

    public void OnDrag(PointerEventData e) { /* ドラッグ中の処理 */ }

    public void OnEndDrag(PointerEventData e)
    {
        Vector2 endPos = e.position;
        float   dt     = Time.time - startTime;
        Vector2 diff   = endPos - startPos;

        if (diff.magnitude >= swipeMinDistance)
            Debug.Log($"UI Swipe: {diff.normalized}");

        if (diff.magnitude >= swipeMinDistance && dt <= flickMaxTime)
            Debug.Log($"UI Flick: {diff.normalized}");
    }
}

iOSネイティブ UIGestureRecognizer との連携

Unityより高精度に フリック速度(速度ベクトル) を取得したい場合、iOSネイティブを使う手もあります。

Objective-C++プラグイン例

 Unity 側で [DllImport(“__Internal”)] void RegisterFlickHandler(); を呼ぶだけで、iOS標準の高速Swipeが取得できます。

#import <UIKit/UIKit.h>

extern "C" {

void RegisterFlickHandler()
{
    dispatch_async(dispatch_get_main_queue(), ^{
        UISwipeGestureRecognizer *swipe =
            [[UISwipeGestureRecognizer alloc] initWithTarget:[UnityAppController sharedInstance]
                                                      action:@selector(handleSwipe:)];
        swipe.direction = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft
                       | UISwipeGestureRecognizerDirectionUp    | UISwipeGestureRecognizerDirectionDown;
        [[[UnityAppController sharedInstance] window] addGestureRecognizer:swipe];
    });
}
}

まとめ

手法特長
標準Input.GetTouch軽量・コピペOK・小規模向け
新Input System+EnhancedTouch高速・マルチタッチ・画面比率対応
UI Event(Drag/Pointer)UI要素専用・EventTrigger連携が簡単
iOSネイティブGestureRecognizerプラグイン速度ベクトル取得・Apple純正の滑らかさ

用途や規模に合わせて選択し、スワイプ&フリック操作を自在に扱いましょう!
ぜひコピペ&カスタマイズであなたのゲームに導入してみてください。