Как отловить ивент свайпа / Swipe в Unity?

81
05 сентября 2019, 20:40

Во многих играх нужно отлавливание жестов, в т.ч. жест свайпа.

Answer 1
Если требуется простая реализация без использования внешних ассетов

для использования класса, который будет ниже, достаточно будет просто подписаться на

SwipeDetector.OnSwipe += SomeMethodCalledBySwipe;

и пример метода:

private void SomeMethodCalledBySwipe(SwipeData data){}

Код класса:

using System;
using UnityEngine;
public class SwipeDetector : MonoBehaviour
{
    private Vector2 _fingerDownPosition;
    private Vector2 _fingerUpPosition;
    [SerializeField]
    private bool _detectSwipeOnlyAfterRelease = false;
    [SerializeField]
    private float _minDistanceForSwipe = 20f;
    public static event Action<SwipeData> OnSwipe = delegate { };
    private void Update()
    {
        SwipeDetectLogic();
    }
    private void SwipeDetectLogic()
    {
        foreach (Touch touch in Input.touches)
        {
            if (touch.phase == TouchPhase.Began)
            {
                _fingerUpPosition = touch.position;
                _fingerDownPosition = touch.position;
            }
            if (!_detectSwipeOnlyAfterRelease && touch.phase == TouchPhase.Moved || 
                touch.phase == TouchPhase.Ended)
            {
                _fingerDownPosition = touch.position;
                DetectSwipe();
            }
        }
    }
    private void DetectSwipe()
    {
        if (SwipeDistanceCheckMet())
        {
            if (IsVerticalSwipe())
            {
                var direction = _fingerDownPosition.y - _fingerUpPosition.y > 0 ? SwipeDirection.Up : SwipeDirection.Down;
                SendSwipe(direction);
            }
            else
            {
                var direction = _fingerDownPosition.x - _fingerUpPosition.x > 0 ? SwipeDirection.Right : SwipeDirection.Left;
                SendSwipe(direction);
            }
            _fingerUpPosition = _fingerDownPosition;
        }
    }
    private bool IsVerticalSwipe()
    {
        return VerticalMovementDistance() > HorizontalMovementDistance();
    }
    private bool SwipeDistanceCheckMet()
    {
        return VerticalMovementDistance() > _minDistanceForSwipe || HorizontalMovementDistance() > _minDistanceForSwipe;
    }
    private float VerticalMovementDistance()
    {
        return Mathf.Abs(_fingerDownPosition.y - _fingerUpPosition.y);
    }
    private float HorizontalMovementDistance()
    {
        return Mathf.Abs(_fingerDownPosition.x - _fingerUpPosition.x);
    }
    private void SendSwipe(SwipeDirection direction)
    {
        SwipeData swipeData = new SwipeData()
        {
            Direction = direction,
            StartPosition = _fingerDownPosition,
            EndPosition = _fingerUpPosition
        };
        OnSwipe(swipeData);
    }
}
public struct SwipeData
{
    public Vector2 StartPosition;
    public Vector2 EndPosition;
    public SwipeDirection Direction;
}
public enum SwipeDirection
{
    Up,
    Down,
    Left,
    Right
}

Код визуализатора/логгера (не обязателен) :

using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class SwipeDebugger : MonoBehaviour
{
    [SerializeField]
    public bool _logging;
    [SerializeField]
    public bool _drawSwipe;
    private LineRenderer _lineRenderer;
    private float _zOffset = 10;
    private void Awake()
    {
        _lineRenderer = GetComponent<LineRenderer>();
        SwipeDetector.OnSwipe += DrawSwipe;
        SwipeDetector.OnSwipe += LogSwipee;
    }
    private void DrawSwipe(SwipeData data)
    {
        if (_drawSwipe)
        {
            Vector3[] positions = new Vector3[2];
            positions[0] = Camera.main.ScreenToWorldPoint(new Vector3(data.StartPosition.x, data.StartPosition.y, _zOffset));
            positions[1] = Camera.main.ScreenToWorldPoint(new Vector3(data.EndPosition.x, data.EndPosition.y, _zOffset));
            _lineRenderer.positionCount = 2;
            _lineRenderer.SetPositions(positions);
        }
    }
    private void LogSwipee(SwipeData data)
    {
        if (_logging)
           Debug.Log("Swipe in Direction: " + data.Direction);
    }
}
Если нужно более гибкое решение:

Есть еще ассет Lean Touch : https://assetstore.unity.com/packages/tools/input-management/lean-touch-30111

Там и свайп более гибкий (что далеко не всегда нужно и далеко не всегда плюс) и поддержка многого функционала вроде тапинга, диагональных свайпов, touch-path и многого другого, что не придется писать самому.

READ ALSO
Как сделать свою бд с IdentityDbContext?

Как сделать свою бд с IdentityDbContext?

Как правильно заполнять таблицу? Создал Custom IdentityUser, создал AccountDatabasemdf, и вроде как создал правильный IdentityDbContex (все как в примере ниже)

131
Вывод елементов от меньшего к большему C#

Вывод елементов от меньшего к большему C#

A, B, C и D – целые коэффициенты кубического уравненияНужно вывести через пробел в порядке возрастания все корни заданного кубического уравнения

86
Как изменить operationId в Swagger?

Как изменить operationId в Swagger?

Обновился до Core 22 В Swagger появилась проблема с operationId

90
Прерывание многопоточности

Прерывание многопоточности

пишу программу, работающую с несколькими модемамиДля ускорения работы использую async await методы и запускаю их асинхронно

78