スマホゲームでキャラクターを移動させたりメニューを開いたりする際、スワイプ(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でマルチタッチ&高速スワイプ
パッケージ設定
- Edit > Project Settings > Player で Active Input Handling = Both
- 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純正の滑らかさ |
用途や規模に合わせて選択し、スワイプ&フリック操作を自在に扱いましょう!
ぜひコピペ&カスタマイズであなたのゲームに導入してみてください。