[TIL] Input System Touch Screen Swipe

Dreamer·2024년 11월 27일

1. 오늘 주제

유니티에서 Input System을 활용하여 터치 이벤트를 받아서 활용하는 법을 남겨본다.

2. 방법

  • Input Action 생성


  • InputController.cs 작성

using UnityEngine;
using UnityEngine.InputSystem;

[DefaultExecutionOrder(-1)]
public class InputController : InitBase
{
    public delegate void StartTouch(Vector2 position, float time);
    public event StartTouch OnStartTouchEvent;

    public delegate void EndTouch(Vector2 position, float time);
    public event EndTouch OnEndTouchEvent;

    private PlayerControls playerControls;
    private Camera mainCamera;

    protected override bool Init()
    {
        if (base.Init() == false)
            return false;

        playerControls = new PlayerControls();
        mainCamera = Camera.main;

        return true;
    }

    private void OnEnable()
    {
        playerControls.Enable();
    }

    private void OnDisable()
    {
        playerControls.Disable();
    }

    private void Start()
    {
        playerControls.Touch.PrimaryContact.started += ctx => OnTouchPrimaryContactStarted(ctx);
        playerControls.Touch.PrimaryContact.canceled += ctx => OnTouchPrimaryContactEnded(ctx);
    }
    
    private void OnTouchPrimaryContactStarted(InputAction.CallbackContext ctx)
    {
        OnStartTouchEvent?.Invoke(
            Utils.ScreenToWorld(
                mainCamera,
                playerControls.Touch.PrimaryPosition.ReadValue<Vector2>()
            ),
            (float)ctx.startTime
        );
    }

    private void OnTouchPrimaryContactEnded(InputAction.CallbackContext ctx)
    {
        OnEndTouchEvent?.Invoke(
            Utils.ScreenToWorld(
                mainCamera,
                playerControls.Touch.PrimaryPosition.ReadValue<Vector2>()
            ),
            (float)ctx.time
        );
    }
    public Vector2 PrimaryPosition()
    {
        return Utils.ScreenToWorld(mainCamera, playerControls.Touch.PrimaryPosition.ReadValue<Vector2>());
    }
}
  • SwipeDetection.cs 작성
using System.Collections;
using UnityEngine;

public class SwipeDetection : MonoBehaviour
{
    [SerializeField] private float minimumSwipeDistance = 0.2f;
    [SerializeField] private float maximumSwipeTime = 1f;
    [SerializeField] private float directionThreshold = 0.9f;
    [SerializeField] private GameObject trail;
    
    private InputController inputController;
    private Vector2 startPosition;
    private float startTime;
    private Vector2 endPosition;
    private float endTime;

    private Coroutine coroutine;
    
    private void Awake()
    {
        inputController = gameObject.GetOrAddComponent<InputController>();
    }

    private void OnEnable()
    {
        inputController.OnStartTouchEvent += SwipeStart;
        inputController.OnEndTouchEvent += SwipeEnd;
    }
    
    private void OnDisable()
    {
        inputController.OnStartTouchEvent -= SwipeStart;
        inputController.OnEndTouchEvent -= SwipeEnd;
    }
    
    private void SwipeStart(Vector2 position, float time)
    {
        startPosition = position;
        startTime = time;
        trail.transform.position = position;
        trail.SetActive(true);
        coroutine = StartCoroutine(Trail());
    }

    private IEnumerator Trail()
    {
        while (true)
        {
            trail.transform.position = inputController.PrimaryPosition();
            yield return null;
        }
    }
    
    private void SwipeEnd(Vector2 position, float time)
    {
        trail.SetActive(false);
        StopCoroutine(coroutine);
        endPosition = position;
        endTime = time;
        
        DetectSwipe();
    }
    
    private void DetectSwipe()
    {
        if (Vector3.Distance(startPosition, endPosition) >= minimumSwipeDistance &&
            (endTime - startTime) <= maximumSwipeTime)
        {
            Debug.Log("Swipe Detected");
            Debug.DrawLine(startPosition, endPosition, Color.red, 5f);
            Vector3 direction = endPosition - startPosition;
            Vector2 direction2D = new Vector2(direction.x, direction.y).normalized;
            SwipeDirection(direction2D);
        }
    }
    
    private void SwipeDirection(Vector2 direction)
    {
        if (Vector2.Dot(Vector2.up, direction) > directionThreshold)
        {
            Debug.Log("Swipe Up");
        }
        else if (Vector2.Dot(Vector2.down, direction) > directionThreshold)
        {
            Debug.Log("Swipe Down");
        }
        else if (Vector2.Dot(Vector2.left, direction) > directionThreshold)
        {
            Debug.Log("Swipe Left");
        }
        else if (Vector2.Dot(Vector2.right, direction) > directionThreshold)
        {
            Debug.Log("Swipe Right");
        }
    }
}
  • Component 달아주고, Trail도 하나 만들어서 넣어주면 된다.

  • 결과물

여기에다가 아무 방향으로 스와이프를 해주면 스와이프를 인식할 수 있다.

profile
새로운 시작

0개의 댓글